Testar se o elemento está presente usando o Selenium WebDriver?

163

Existe uma maneira de testar se um elemento está presente? Qualquer método findElement terminaria em uma exceção, mas não é isso que eu quero, porque pode ser que um elemento não esteja presente e que esteja bem, que não seja uma falha no teste, portanto uma exceção não pode ser a solução.

Eu encontrei este post: Selenium c # Webdriver: Aguarde até que o elemento esteja presente Mas isso é para C # e eu não sou muito bom nisso. Alguém pode traduzir o código em Java? Desculpe pessoal, tentei no Eclipse, mas não entendi direito no código Java.

Este é o código:

public static class WebDriverExtensions{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){

        if (timeoutInSeconds > 0){
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }

        return driver.FindElement(by);
    }
}
testador
fonte
Eu tenho alguns métodos que funcionam muito efetivamente na verificação de um objeto, mas isso depende do que você deseja fazer com ele. por exemplo, você deseja procurar o elemento até que ele exista, deseja procurá-lo até que ele não exista mais ou deseja apenas tentar encontrá-lo?
CBRRacer #
1
Java é muito semelhante ao C # Eu acho que um dos principais problemas que você está correndo para aqui é em java-lo de WebElement vez de IWebElement
CBRRacer
Você conhece o método de espera implícita? Ao fazer essa configuração no início do teste que você nunca tem que verificar para a existência de um elemento como é usa o valor de espera implícita a pesquisa, no entanto, se exceder esse valor vai lançar uma exceção
Bob Evans
Aqui está o meu post sobre o WebDriverWait em Java: WebDriverWait
Se qualquer um dos casos estiver correto, isso pode ser problemático para o desempenho do teste, pois o tempo de espera associado à espera de um elemento que você não espera existir realmente aumenta. Usei alguns hacks para evitar o tempo de espera, mas ainda precisamos encontrar uma solução realmente limpa para isso.
precisa saber é o seguinte

Respostas:

277

Use em findElementsvez de findElement.

findElements retornará uma lista vazia se nenhum elemento correspondente for encontrado em vez de uma exceção.

Para verificar se um elemento está presente, você pode tentar isso

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

Isso retornará true se pelo menos um elemento for encontrado e false se ele não existir.

A documentação oficial recomenda este método:

findElement não deve ser usado para procurar elementos não presentes, use findElements (By) e, em vez disso, afirme uma resposta de comprimento zero.

el roso
fonte
32
Isso adicionará muito tempo para executar seus testes. Você não pode usar esta técnica em qualquer lugar.
Droogans
8
@Droogans - não adicionarei tempo aos seus testes. O motivo é que a espera implícita padrão ainda é 0. Se você aumentou a espera implícita padrão, concordo que sim, mas não parece ser o caso aqui.
djangofan
1
Boa chamada djangofan! Eu usei essa estratégia com êxito, alterando a espera implícita dos tempos limite do driver para zero e, em seguida, retornando ao seu valor anterior.
esmeril
3
Isso deu uma exceção NoSuchElementFound, o que é uma pena, pois eu esperava usá-lo para evitar capturar essa exceção em uma determinada instância.
1
Uma maneira muito mais fácil é usar: if (driver.getPageSource (). Contains ("A text in page")) {} Se a página contiver esse texto, a condição será verdadeira, ou será falsa e você poderá codificar adequadamente.
pradyot
56

Que tal um método privado que simplesmente procura o elemento e determina se ele está presente assim:

private boolean existsElement(String id) {
    try {
        driver.findElement(By.id(id));
    } catch (NoSuchElementException e) {
        return false;
    }
    return true;
}

Isso seria bastante fácil e faz o trabalho.

Edit: você pode ir além e usar um By elementLocatorparâmetro as, eliminando problemas se desejar encontrar o elemento por algo diferente de id.

Dennis
fonte
3
Sim, este é o caminho a percorrer. Não entendo por que as pessoas estão ignorando desta forma, e contando elementos correspondentes, vendo se o resultado é 0.
Ralph Lavelle
45
Bem, devo dizer que usar exceções para regular o fluxo do programa não é o melhor caminho a percorrer.
Dennis
2
Hã? Foi sua sugestão! É um bom caminho a percorrer se o seu teste espera não encontrar o elemento. Como você mostra, basta retornar null e assert.isnull ou isnotnull, que é uma maneira significativa de testar se existe algo.
Ralph Lavelle
2
Caso eu tenha interpretado mal a pergunta "existe uma maneira de testar se um elemento está presente?" errado, terei prazer em saber por que sua opinião difere sobre se essa é uma resposta legítima ou não.
Dennis
pode querer reduzir o tempo de espera. Agora, se o elemento não existir, você deve esperar "30 segundos" antes da função retorna FALSE
Jason Smiley
14

Eu descobri que isso funciona para Java:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);
Tango Ben
fonte
18
presenceOfElementLocatedemitirá uma exceção se o elemento não for encontrado em nenhuma tentativa específica. Para evitar isso, adicione uma wait.ignoring(NoSuchElementException.class);declaração entre a primeira e a segunda linha.
Steve Chambers
8
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
    WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
    wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
    return driver.findElement(by);
}
RedDeckWins
fonte
5

Eu tive o mesmo problema. Para mim, dependendo do nível de permissão do usuário, alguns links, botões e outros elementos não serão exibidos na página. Parte da minha suíte estava testando que os elementos que DEVEM estar faltando estão faltando. Passei horas tentando descobrir isso. Finalmente encontrei a solução perfeita.

O que isso faz é dizer ao navegador para procurar todos e quaisquer elementos com base especificados. Se resultar 0, significa que nenhum elemento baseado na especificação foi encontrado. Então eu tenho o código executar uma instrução if para que eu saiba que não foi encontrado.

Como está C#, então as traduções precisariam ser feitas para Java. Mas não deve ser muito difícil.

public void verifyPermission(string link)
{
    IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
    if (adminPermissions.Count == 0)
    {
        Console.WriteLine("User's permission properly hidden");
    }
}

Há também outro caminho que você pode seguir, dependendo do que você precisa para o seu teste.

O seguinte snippet está verificando se existe um elemento muito específico na página. Dependendo da existência do elemento, tenho o teste para executar um if else.

Se o elemento existir e for exibido na página, console.writeinforme-me e seguir em frente. Se o elemento em questão existir, não posso executar o teste necessário, que é o principal motivo por trás da necessidade de configurá-lo.

Se o elemento Não existir e não for exibido na página. Eu tenho o else no if else executar o teste.

IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
//if the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute whats in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
    //script to execute if element is found
} else {
    //Test script goes here.
}

Eu sei que estou um pouco atrasado na resposta ao OP. Espero que isso ajude alguém!

Tasha
fonte
5

Tente isto: chame este método e passe 3 argumentos:

  1. Variável WebDriver. // assumindo driver_variable como driver.
  2. O elemento que você está indo verificar. Deve fornecer pelo método. // ex: By.id ("id")
  3. Prazo em segundos.

Exemplo: waitForElementPresent (driver, By.id ("id"), 10);

public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {

        WebElement element; 

        try{
            driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

            WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
            element = wait.until(ExpectedConditions.presenceOfElementLocated(by));

            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //reset implicitlyWait
            return element; //return the element
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null; 
    }
Prabu Ananthakrishnan
fonte
3

Você pode executar o código mais rapidamente, reduzindo o tempo limite do selênio antes de sua instrução try catch.

Eu uso o código a seguir para verificar se um elemento está presente.

protected boolean isElementPresent(By selector) {
    selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
    logger.debug("Is element present"+selector);
    boolean returnVal = true;
    try{
        selenium.findElement(selector);
    } catch (NoSuchElementException e){
        returnVal = false;
    } finally {
        selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    }
    return returnVal;
}
EsotericNonsense
fonte
É isso que eu uso no meu código. Deixo o tempo limite do Selenium no padrão e depois o uso.
Nicholas DiPiazza
2
Desde que escrevi essa resposta, aprendi que usar ExpectedConditions é considerado uma forma melhor, mas usar uma instrução try catch ainda é útil ao tentar determinar se um elemento não está presente.
EsotericNonsense
Estou preso em uma versão antiga do selênio, porque eu tenho que testar o IE8. Mas vou tentar que, quando eu posso atualizar
Nicholas DiPiazza
Cada vez que seu método definirá o tempo limite de espera implícito, mas logicamente devemos definir a espera implícita apenas uma vez após a inicialização do objeto do driver e o tempo limite ser definido para a sessão do driver.
Shekhar Swami
3

Escreva a seguinte função / methos usando Java:

protected boolean isElementPresent(By by){
        try{
            driver.findElement(by);
            return true;
        }
        catch(NoSuchElementException e){
            return false;
        }
    }

Chame o método com o parâmetro apropriado durante a asserção.

Ripon Al Wasim
fonte
2

se você estiver usando o rspec-Webdriver em ruby, poderá usar este script assumindo que um elemento realmente não deve estar presente e que seja um teste aprovado.

Primeiro, escreva esse método primeiro no seu arquivo RB de classe

class Test
 def element_present?
    begin
        browser.find_element(:name, "this_element_id".displayed?
        rescue Selenium::WebDriver::Error::NoSuchElementError
            puts "this element should not be present"
        end
 end

Em seguida, no seu arquivo de especificação, chame esse método.

  before(:all) do    
    @Test= Test.new(@browser)
  end

 @Test.element_present?.should == nil

Se o elemento NÃO estiver presente, sua especificação será aprovada, mas se o elemento estiver presente, ocorrerá um erro, o teste falhou.

grayshell
fonte
2

Isso funciona para mim:

 if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
    //THEN CLICK ON THE SUBMIT BUTTON
}else{
    //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}
Amstel Bytes
fonte
o mesmo problema existe aqui: e se o elemento "// * [@ id = 'submit']" não existir? em seguida, uma exceção será lançada, assim, a se condicional não avalia
MrBCut
1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }
Bogdan Shulga
fonte
1

Pessoalmente, sempre busco uma mistura das respostas acima e crio um método Utility estático reutilizável que usa a size() > 0sugestão:

public Class Utility {
   ...
   public static boolean isElementExist(WebDriver driver, By by) {
      return driver.findElements(by).size() > 0;
   ...
}

Isso é puro, reutilizável, sustentável ... todas essas coisas boas ;-)

Charlie Seligman
fonte
0

Para encontrar um elemento em particular presente ou não, precisamos usar o método findElements () em vez de findElement () ..

int i=driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");

isso é trabalhado para mim .. me sugerir se eu estiver errado ..

Subbarao Gaddam
fonte
0

Isso deve servir:

try {
    driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
    //do what you need here if you were expecting
    //the element wouldn't exist
}
Scott Helme
fonte
0

Dando meu trecho de código. Portanto, o método abaixo verifica se existe um elemento aleatório da Web no botão ' Criar novo aplicativo ' em uma página ou não. Observe que eu usei o período de espera como 0 segundos.

public boolean isCreateNewApplicationButtonVisible(){
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='Create New Application']"));
    try {
        zeroWait.until(c);
        logger.debug("Create New Application button is visible");
        return true;
    } catch (TimeoutException e) {
        logger.debug("Create New Application button is not visible");
        return false;
    }
}
Rambo7
fonte
0

Eu usaria algo como (com Scala [o código no antigo Java "bom" 8 pode ser semelhante a este]):

object SeleniumFacade {

  def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
    val elements = maybeParent match {
      case Some(parent) => parent.findElements(bySelector).asScala
      case None => driver.findElements(bySelector).asScala
    }
    if (elements.nonEmpty) {
      Try { Some(elements(withIndex)) } getOrElse None
    } else None
  }
  ...
}

Então,

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))
ses
fonte
0

A maneira mais simples que encontrei em Java é:

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink=linkSearch.size();
if(checkLink!=0){  //do something you want}
back2back
fonte
0

Você pode tentar a espera implícita:

WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));

Ou você pode tentar esperar explicitamente um:

IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
    {
        return d.FindElement(By.Id("someDynamicElement"));
    });

Explícito irá verificar se o elemento está presente antes de alguma ação. A espera implícita pode ser chamada em todos os lugares do código. Por exemplo, depois de algumas ações AJAX.

Mais você pode encontrar na página SeleniumHQ

estressante
fonte