Gosto da sua ideia de pesquisar o HTML até que esteja estável. Posso adicionar isso à minha própria solução. A abordagem a seguir está em C # e requer jQuery.
Sou o desenvolvedor de um projeto de teste SuccessFactors (SaaS) em que não temos nenhuma influência sobre os desenvolvedores ou as características do DOM por trás da página da web. O produto SaaS pode alterar potencialmente seu design de DOM subjacente 4 vezes por ano, de modo que a busca é permanente por maneiras robustas e de alto desempenho de testar com Selenium (incluindo NÃO testar com Selenium quando possível!)
Aqui está o que eu uso para "página pronta". Ele funciona em todos os meus próprios testes atualmente. A mesma abordagem também funcionou para um grande aplicativo da web Java interno alguns anos atrás, e já era robusta por mais de um ano na época em que deixei o projeto.
Driver
é a instância do WebDriver que se comunica com o navegador
DefaultPageLoadTimeout
é um valor de tempo limite em ticks (100ns por tick)
public IWebDriver Driver { get; private set; }
// ...
const int GlobalPageLoadTimeOutSecs = 10;
static readonly TimeSpan DefaultPageLoadTimeout =
new TimeSpan((long) (10_000_000 * GlobalPageLoadTimeOutSecs));
Driver = new FirefoxDriver();
A seguir, observe a ordem das esperas no método PageReady
(documento Selenium pronto, Ajax, animações), o que faz sentido se você pensar bem:
- carregue a página que contém o código
- use o código para carregar os dados de algum lugar via Ajax
- apresentar os dados, possivelmente com animações
Algo como a abordagem de comparação do DOM pode ser usado entre 1 e 2 para adicionar outra camada de robustez.
public void PageReady()
{
DocumentReady();
AjaxReady();
AnimationsReady();
}
private void DocumentReady()
{
WaitForJavascript(script: "return document.readyState", result: "complete");
}
private void WaitForJavascript(string script, string result)
{
new WebDriverWait(Driver, DefaultPageLoadTimeout).Until(
d => ((IJavaScriptExecutor) d).ExecuteScript(script).Equals(result));
}
private void AjaxReady()
{
WaitForJavascript(script: "return jQuery.active.toString()", result: "0");
}
private void AnimationsReady()
{
WaitForJavascript(script: "return $(\"animated\").length.toString()", result: "0");
}