Vou manter a opinião impopular sobre a tag selênio do SO de que XPath é preferível a CSS a longo prazo.
Esta longa postagem tem duas seções - primeiro vou colocar uma prova de trás do guardanapo de que a diferença de desempenho entre os dois é de 0,1-0,3 milissegundos (sim; são 100 microssegundos ) , e então compartilharei minha opinião por que XPath é mais poderoso.
Diferença de desempenho
Vamos primeiro abordar "o elefante na sala" - esse xpath é mais lento que o css.
Com o poder da CPU atual (leia-se: qualquer coisa x86 produzida desde 2013) , mesmo nas VMs browserstack / saucelabs / aws, e o desenvolvimento dos navegadores (leia-se: todos os populares nos últimos 5 anos) isso dificilmente é o caso. Os motores do navegador foram desenvolvidos, o suporte do xpath é uniforme, o IE está fora de cogitação (espero que para a maioria de nós) . Essa comparação na outra resposta está sendo citada em todos os lugares, mas é muito contextual - quantos estão executando - ou se preocupam com - automação contra o IE8?
Se houver diferença, é em uma fração de milissegundo .
Ainda assim, a maioria das estruturas de nível superior adiciona pelo menos 1 ms de sobrecarga sobre a chamada de selênio bruto de qualquer maneira (wrappers, manipuladores, armazenamento de estado etc); minha arma pessoal de escolha - RobotFramework - adiciona pelo menos 2ms, que estou mais do que feliz em sacrificar pelo que ele oferece. Uma viagem de ida e volta da rede de um AWS us-east-1 para o hub do BrowserStack geralmente dura 11 milissegundos .
Portanto, com navegadores remotos, se houver uma diferença entre xpath e css, ela será ofuscada por todo o resto, em ordens de magnitude.
As medições
Não há muitas comparações públicas (eu realmente vi apenas a citada) , então - aqui está um caso simples, fictício e simples.
Ele localizará um elemento pelas duas estratégias X vezes e comparará o tempo médio para isso.
O destino - a página de destino do BrowserStack e seu botão "Cadastre-se"; uma captura de tela do html ao escrever este post:
Aqui está o código de teste (python):
from selenium import webdriver
import timeit
if __name__ == '__main__':
xpath_locator = '//div[@class="button-section col-xs-12 row"]'
css_locator = 'div.button-section.col-xs-12.row'
repetitions = 1000
driver = webdriver.Chrome()
driver.get('https://www.browserstack.com/')
css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)",
number=repetitions, globals=globals())
xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)',
number=repetitions, globals=globals())
driver.quit()
print("css total time {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, css_time, (css_time/repetitions)*1000))
print("xpath total time for {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, xpath_time, (xpath_time/repetitions)*1000))
Para quem não está familiarizado com Python - ele abre a página e encontra o elemento - primeiro com o localizador css, depois com o xpath; a operação de localização é repetida 1.000 vezes. A saída é o tempo total em segundos para as 1.000 repetições e o tempo médio para uma descoberta em milissegundos.
Os localizadores são:
- para xpath - "um elemento div com este valor de classe exato, em algum lugar do DOM";
- o css é semelhante - "um elemento div com esta classe, em algum lugar do DOM".
Deliberadamente escolhido para não ser excessivamente ajustado; além disso, o seletor de classe é citado para o css como "o segundo mais rápido depois de um id".
O ambiente - Chrome v66.0.3359.139, chromedriver v2.38, cpu: ULV Core M-5Y10 geralmente rodando a 1,5 GHz (sim, um "processador de texto", nem mesmo um i7 besta regular) .
Aqui está o resultado:
css total time 1000 repeats: 8.84s, per find: 8.84ms
xpath total time for 1000 repeats: 8.52s, per find: 8.52ms
Obviamente, os tempos de busca são bem próximos; a diferença é de 0,32 milissegundos . Não pule "o xpath é mais rápido" - às vezes é, às vezes é css.
Vamos tentar com outro conjunto de localizadores, um pouco mais complicado - um atributo com uma substring (abordagem comum, pelo menos para mim, ir atrás da classe de um elemento quando uma parte dela tem um significado funcional) :
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
Os dois localizadores são semanticamente iguais - "encontre um elemento div tendo em seu atributo de classe esta substring".
Aqui estão os resultados:
css total time 1000 repeats: 8.60s, per find: 8.60ms
xpath total time for 1000 repeats: 8.75s, per find: 8.75ms
Dif de 0,15ms .
Como um exercício - o mesmo teste feito no blog vinculado nos comentários / outra resposta - a página de teste é pública, assim como o código de teste .
Eles estão fazendo algumas coisas no código - clicando em uma coluna para classificar por ela, depois obtendo os valores e verificando se a classificação da IU está correta.
Vou cortar - basta pegar os localizadores, afinal - esse é o teste de raiz, certo?
O mesmo código acima, com essas alterações em:
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
E aqui está o resultado:
css total time 1000 repeats: 8.24s, per find: 8.24ms
xpath total time for 1000 repeats: 8.45s, per find: 8.45ms
Diferença de 0,2 milissegundos.
O "Finding Elements By Traversing":
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
O resultado:
css total time 1000 repeats: 9.29s, per find: 9.29ms
xpath total time for 1000 repeats: 8.79s, per find: 8.79ms
Desta vez, é 0,5 ms (ao contrário, xpath saiu "mais rápido" aqui).
Então, 5 anos depois (motores de navegadores melhores) e com foco apenas no desempenho dos localizadores (sem ações como ordenar na IU, etc), o mesmo testbed - não há praticamente nenhuma diferença entre CSS e XPath.
Então, de xpath e css, qual dos dois escolher para desempenho? A resposta é simples - escolha a localização por id .
Resumindo, se o id de um elemento é único (como deveria ser de acordo com as especificações), seu valor desempenha um papel importante na representação interna do navegador do DOM e, portanto, é geralmente o mais rápido.
No entanto, ids únicos e constantes (por exemplo, não gerados automaticamente) nem sempre estão disponíveis, o que nos leva a "por que XPath se existe CSS?"
A vantagem do XPath
Com o desempenho fora de cogitação, por que acho que o xpath é melhor? Simples - versatilidade e potência.
Xpath é uma linguagem desenvolvida para trabalhar com documentos XML; como tal, ele permite construções muito mais poderosas do que o css.
Por exemplo, navegação em todas as direções da árvore - encontre um elemento, vá até seu avô e procure um filho dele com certas propriedades.
Ele permite condições booleanas embutidas - cond1 and not(cond2 or not(cond3 and cond4))
; seletores incorporados - "encontre um div que tenha esses filhos com esses atributos e navegue de acordo com ele".
XPath permite pesquisar com base no valor de um nó (seu texto) - por mais desaprovado que essa prática seja, ela é útil especialmente em documentos mal estruturados (sem atributos definidos para pisar, como ids dinâmicos e classes - localize o elemento por seu texto conteúdo) .
A etapa em css é definitivamente mais fácil - pode-se começar a escrever seletores em questão de minutos; mas depois de alguns dias de uso, o poder e as possibilidades do xpath superam rapidamente o css.
E puramente subjetivo - um css complexo é muito mais difícil de ler do que uma expressão xpath complexa.
Outro;)
Finalmente, novamente muito subjetivo - qual escolher?
IMO, não há escolha certa ou errada - são soluções diferentes para o mesmo problema, e o que for mais adequado para o trabalho deve ser escolhido.
Sendo "um fã" do XPath, não tenho vergonha de usar em meus projetos uma mistura dos dois - caramba, às vezes é muito mais rápido apenas lançar um CSS, se eu souber que fará o trabalho muito bem.