Мне нравится ваша идея опросить HTML, пока он не станет стабильным. Я могу добавить это к своему собственному решению. Следующий подход основан на C # и требует jQuery.
Я разработчик тестового проекта SuccessFactors (SaaS), в котором мы не имеем никакого влияния на разработчиков или характеристики модели DOM, лежащей в основе веб-страницы. Продукт SaaS потенциально может изменять свой основной дизайн DOM 4 раза в год, поэтому постоянно ведется охота за надежными и производительными способами тестирования с помощью Selenium (включая НЕ тестирование с помощью Selenium, где это возможно!)
Вот что я использую для слова «страница готова». В настоящее время он работает во всех моих собственных тестах. Тот же подход работал и для большого собственного веб-приложения на Java пару лет назад, и к тому моменту, когда я покинул проект, он был надежным более года.
Driver
это экземпляр WebDriver, который взаимодействует с браузером
DefaultPageLoadTimeout
значение тайм-аута в тиках (100 нс за тик)
public IWebDriver Driver { get; private set; }
// ...
const int GlobalPageLoadTimeOutSecs = 10;
static readonly TimeSpan DefaultPageLoadTimeout =
new TimeSpan((long) (10_000_000 * GlobalPageLoadTimeOutSecs));
Driver = new FirefoxDriver();
В дальнейшем обратите внимание на порядок ожидания в методе PageReady
(готовность документа Selenium, Ajax, анимация), который имеет смысл, если вы задумаетесь:
- загрузить страницу, содержащую код
- используйте код для загрузки данных откуда-нибудь через Ajax
- представить данные, возможно, с анимацией
Что-то вроде вашего подхода к сравнению DOM можно использовать между 1 и 2, чтобы добавить еще один уровень надежности.
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");
}