Сам Thread.Sleep ничем не плох и не хорош.
В моем коде, Thread.Sleep(100) используется для задержки на 100 миллисекунд в цикле, ожидания элемента для того, чтобы не напрягать браузер частыми запросами.
Т.е. в худшем случае, вы потеряете 1/10-ю секунды при ожидании одного элемента. Все относительно.
Для WebDriver тестов — это мало. Для юнит тестов и торговле на бирже ценных бумаг — это много.
Плохой практикой Thread.Sleep() становится, когда люди указывают константное время, например, 5 секунд для ожидания элемента.
Потом оказывается, что в IE, нужно подождать 10 секунд…
Тогда меняют Thread.Sleep(5000) на Thread.Sleep(10000)… и теперь тесты во всех браузерах работают со скоростью самого медленного.
Очень рекомендую записать скринкаст с демонстрациией возможностей фреймворка.
Для начала, простой «Getting Started… „
Только не в виде “вебинара», которые очень скучные и длинные, а в стиле Pluralsite или Lynda.
Я заметил, что запись моего «кодирования» можно ускорить в 2-4 раза, при этом, видео не потеряет в качестве. А всякие длинные установки, билды и скачивания можно и вовсе вырезать.
На видео потом, можно наложить как русскоязычную так и англоязычную звуковую дорожку. А следующую статью составить на основе уже записанного видео.
Удачи вам, Сергей, с проектом и последующим маркетингом :D
Сергей, не в обиду, но я читал вашу статью год назад. И через год… ваш стиль написания статьи полон сумбура.
Вы пытаетесь охватить всё на свете в одной теме. Становится непонятно, для кого эта статья написана.
Если вы хотите, чтобы начинающие автоматизаторы попробовали ваш фреймворк, то я рекомендую начать с более простой обзорной статьи и видео демонстрации работы, развивая более глубокие темы в следующих.
Если это только первая версия и MVP (Minimum Valuable Product) – то должен сказать, что получилось достаточно хорошо. Все таки написать с скомпоновать что-то и отдать «критикам» все во много лучше, чем спросить «Ребята, я тут книгу пишу, не подскажите о чем лучше написать?» – как это делают другие.
Успехов с версией 2.0!
Честно сказать, книга мне не показалась очень полезной. Возможно потому, что ваши статьи читал раньше, особенно те холиварные на ДОУ и Хабре. В свое время это было очень круто. Сейчас же, я хотел бы видеть более рафинированные мысли: избавится от неактуальных фактов, дать более чёткий совет.
Вот например из последней статьи (31 марта 2013 г.):
«Недавно проскользнула довольно-таки интересная статья о том, что в одной из
известных сервисных компаний собраны все ИТ-знания мира»
Хм… очень смутно представляю что такое недавно сейчас… для середины 2014-го года.
В общем, я бы хотел видеть рассказ о прошлых поступках и о топ как бы Автор поступил сейчас, больший багаж опыта за спиной. Ну что-то в таком духе.
А за бесплатную электронную книгу без СМС и регистрации – спасибо!
Treshnikov, спасибо за то, что делитесь информацией, а особенно об использовании WebDriver с PageObject'ами.
Разрешите мне также поделится теми наблюдениями, чем мой подход при работе с WebDriver отличается от вашего:
Сразу скажу, что у вас хорошее решение со Step(“step step step”) ;)
1. Я бы сразу разделил код на 3 проекта: отдельно тесты (AcceptanceTesting.Tests), отдельно библиотека с PageObject (AcceptanceTesting.TestModel), отдельно другие библиотечные функции (AcceptanceTesting.Core). – к этому все равно приходят, когда тестов станет много и их захочится разделить на несколько тестовых наборов для запуска параллельно
2. Для себя я выработал правило: стараться не использовать вебэлементы и другие вызовы вебдрайвера непосредственно в тесте, а использовать только вызовы методов PageObject.
Т.е. сделать так, чтобы тесты не знали, что они работают с WebDriver.
Вот, например, этот код я бы оставил не измененным:
Step("Первая ссылка должна содержать адрес sms-automation.ru",
() =>
{
var href = googleSearchResultPage.FirstLink.GetAttribute("href");
Assert.AreEqual(href, "http://www.sms-automation.ru/");
});
на
Step("Первая ссылка должна содержать адрес sms-automation.ru",
() =>
{
var href = googleSearchResultPage.GetFirstLink();
// или
// var href = googleSearchResultPage.GetAllLinks().First();
Assert.AreEqual(href, "http://www.sms-automation.ru/");
});
Спасибо вам еще раз, за то, что делитесь знаниями и хорошими подходами!
Минутка самопиара:
А посмотрите ещё мой Page Recorder, который может ускорить процесс создания PageObject классов.
Я считаю, что это круто. Думаю, что сейчас, конечно, не так много найдется людей, который бы работали с екселем и умели рабоать с JavaScript / HTML. Пока это еще не так просто.
Тем не менее, вышибающие мозг формулы ведь создавать научились :)
Мне коротко объяснить всю эту штуку сложно, но я попробую.
В общем, если элемент txtCaptcha находится на физической странице Page 2, то и объявить его необходимо в классе Page2. Это вы верно говорите.
Для того, чтобы выяснить из метода Page1.GotoPage2(), отображается ли уже Page2 на экране или ещё нет, мы вызываем Page2.IsDisplayed().
В случае, если Page2.IsDisplayed() вернёт true – ничего делать не нужно. Страница Page2 уже открыта.
В случае false – нам необходимо проделать некоторые действия на странице Page1 для того, чтобы появилась Page2.
У меня есть доклад, в котором я менее скомканным образом рассказываю про эту тему.
Там же есть пример кода взаимодействия между страницами:
Обычно, такой проверки на то, что Page2 загрузилась не требуется.
Например, в следующем коде:
var page1 = new Page1;
var page2 = page1.GoToPage2(); // ①
page2.DoSomeStuff(); // ②
При условии того, что Page2 не была загружена, строка ② просто упадёт. Если тесты снимают скриншот страницы автоматом при падении, то по нему будет видно, что страница 2 небыла загружена.
Второй вариант, это введение отдельного метода IsDisplayed, как в примере CreateNewAccountPage.cs для каждой страницы.
public override bool IsDisplayed()
{
return txtCaptcha.Displayed;
}
Смысл метода в том, что он определяет открыта ли страница по некоторому уникальному условию. В примере – это условия отображения контрола txtCaptcha на странице.
Для каждой страницы проверка на существование должно быть уникальным.
Да, это была простая операция. И я догадался что она делает, хоть и были сомнения.
Тем не менее, для достижения самодокументированого кода, необходимо выносить логически завершенные блоки кода в отдельные методы. Тогда код будет рассказывать ЧТО он делает, а не только КАК он это делает.
Это правило должно применяться как к одной строчки кода, так и к 5-ти, например.
Если не хотите множить сущности, то всегда можно добавить комментарий:
// Return if directory is empty
или // Return ifthere are no .dll files in the directory
А если не хотите добавлять комментарий — тоже не беда. Рано или поздно тот, кто будет читать код, с ним все равно разберется.
Спасибо, lavice, за качественный перевод. Приятно читать.
Честно говоря, этот текст от автора книги не укладывается у меня в голове. Я рассчитывал, что будет постепенный список того, что можно автоматизировать, несколько советов, по типу автоматизации рутины, может-быть создания своих плагинов для какого-нибудь софта…
Но тут: резкий скачек от “у нас ничего не автоматизировалось” до генерации кода на основе модели. Такой подход, конечно же существует, но я не скажу, что он настолько сильно распространен из-за сложности создания самой модели.
Если брать пример из главы, то мне кажется, легче будет 20 сайтов с корзиной, путь даже на собственном движке, наклепать, чем одну модель все это время разрабатывать.
Опять же, не ясна фраза с генерацией кода. Т.е., конечно же, во многих ситуациях, генерация части кода оправдана, как то создание UI интерфейсов или классы, декларирующие поля базы данных. Но, насколько я понял, автор хочет сгенерировать весь код приложения.
В формуле с рейтами программиста, явно рассматриваются какие-то предельные ситуации: “очень хороший и дорогой”, “дешевый и плохой”.
Будто-бы, посередине ничего нет. Я думаю, за рейт $45, можно вполне найти очень хорошего разработчика на просторах СНГ, так и в Индии (ведь, не все же там индокодят, просто тех, кто индокодит — большее число)
К сожалению, мне не удалось воспроизвести проблему с Win7 32-bit + FF 26.
Сама проблема кроется где-то в недрах .NET Framework.
Как последний из вариантов, которые у меня есть,
я прошу вас попробовать установить или обновить полный .NET Framework 4, который можно скачать по следующей ссылке:
Скрипт для прохождения (или тестирования): gist.github.com/dzharii/1fce1ef335d0073c0ded
Геймплей:
В моем коде, Thread.Sleep(100) используется для задержки на 100 миллисекунд в цикле, ожидания элемента для того, чтобы не напрягать браузер частыми запросами.
Т.е. в худшем случае, вы потеряете 1/10-ю секунды при ожидании одного элемента. Все относительно.
Для WebDriver тестов — это мало. Для юнит тестов и торговле на бирже ценных бумаг — это много.
Плохой практикой Thread.Sleep() становится, когда люди указывают константное время, например, 5 секунд для ожидания элемента.
Потом оказывается, что в IE, нужно подождать 10 секунд…
Тогда меняют Thread.Sleep(5000) на Thread.Sleep(10000)… и теперь тесты во всех браузерах работают со скоростью самого медленного.
Вот это — плохая практика.
cube-drone.com/2014_02_19-Cube_Drone_76_Many_Angular_Ones.html
Для начала, простой «Getting Started… „
Только не в виде “вебинара», которые очень скучные и длинные, а в стиле Pluralsite или Lynda.
Я заметил, что запись моего «кодирования» можно ускорить в 2-4 раза, при этом, видео не потеряет в качестве. А всякие длинные установки, билды и скачивания можно и вовсе вырезать.
На видео потом, можно наложить как русскоязычную так и англоязычную звуковую дорожку. А следующую статью составить на основе уже записанного видео.
Удачи вам, Сергей, с проектом и последующим маркетингом :D
Вы пытаетесь охватить всё на свете в одной теме. Становится непонятно, для кого эта статья написана.
Если вы хотите, чтобы начинающие автоматизаторы попробовали ваш фреймворк, то я рекомендую начать с более простой обзорной статьи и видео демонстрации работы, развивая более глубокие темы в следующих.
Успехов с версией 2.0!
password2010?
Честно сказать, книга мне не показалась очень полезной. Возможно потому, что ваши статьи читал раньше, особенно те холиварные на ДОУ и Хабре. В свое время это было очень круто. Сейчас же, я хотел бы видеть более рафинированные мысли: избавится от неактуальных фактов, дать более чёткий совет.
Вот например из последней статьи (31 марта 2013 г.):
«Недавно проскользнула довольно-таки интересная статья о том, что в одной из
известных сервисных компаний собраны все ИТ-знания мира»
Хм… очень смутно представляю что такое недавно сейчас… для середины 2014-го года.
В общем, я бы хотел видеть рассказ о прошлых поступках и о топ как бы Автор поступил сейчас, больший багаж опыта за спиной. Ну что-то в таком духе.
А за бесплатную электронную книгу без СМС и регистрации – спасибо!
Разрешите мне также поделится теми наблюдениями, чем мой подход при работе с WebDriver отличается от вашего:
Сразу скажу, что у вас хорошее решение со Step(“step step step”) ;)
1. Я бы сразу разделил код на 3 проекта: отдельно тесты (AcceptanceTesting.Tests), отдельно библиотека с PageObject (AcceptanceTesting.TestModel), отдельно другие библиотечные функции (AcceptanceTesting.Core). – к этому все равно приходят, когда тестов станет много и их захочится разделить на несколько тестовых наборов для запуска параллельно
2. Для себя я выработал правило: стараться не использовать вебэлементы и другие вызовы вебдрайвера непосредственно в тесте, а использовать только вызовы методов PageObject.
Т.е. сделать так, чтобы тесты не знали, что они работают с WebDriver.
Вот, например, этот код я бы оставил не измененным:
А вот этот бы заменил
на
Спасибо вам еще раз, за то, что делитесь знаниями и хорошими подходами!
Минутка самопиара:
А посмотрите ещё мой Page Recorder, который может ускорить процесс создания PageObject классов.
Тем не менее, вышибающие мозг формулы ведь создавать научились :)
В общем, если элемент txtCaptcha находится на физической странице Page 2, то и объявить его необходимо в классе Page2. Это вы верно говорите.
Для того, чтобы выяснить из метода Page1.GotoPage2(), отображается ли уже Page2 на экране или ещё нет, мы вызываем Page2.IsDisplayed().
В случае, если Page2.IsDisplayed() вернёт true – ничего делать не нужно. Страница Page2 уже открыта.
В случае false – нам необходимо проделать некоторые действия на странице Page1 для того, чтобы появилась Page2.
У меня есть доклад, в котором я менее скомканным образом рассказываю про эту тему.
Там же есть пример кода взаимодействия между страницами:
blog.zhariy.com/2013/02/atdays-pageobject.html
Посмотрите пожалуйста, если будет что-то не ясно, то я придумаю как продемонстрировать все наглядней.
Например, в следующем коде:
При условии того, что Page2 не была загружена, строка ② просто упадёт. Если тесты снимают скриншот страницы автоматом при падении, то по нему будет видно, что страница 2 небыла загружена.
Второй вариант, это введение отдельного метода IsDisplayed, как в примере CreateNewAccountPage.cs для каждой страницы.
Смысл метода в том, что он определяет открыта ли страница по некоторому уникальному условию. В примере – это условия отображения контрола txtCaptcha на странице.
Для каждой страницы проверка на существование должно быть уникальным.
Тем не менее, для достижения самодокументированого кода, необходимо выносить логически завершенные блоки кода в отдельные методы. Тогда код будет рассказывать ЧТО он делает, а не только КАК он это делает.
Это правило должно применяться как к одной строчки кода, так и к 5-ти, например.
Если не хотите множить сущности, то всегда можно добавить комментарий:
// Return if directory is empty
или
// Return ifthere are no .dll files in the directory
А если не хотите добавлять комментарий — тоже не беда. Рано или поздно тот, кто будет читать код, с ним все равно разберется.
Комментарии в коде пишутся для того, чтобы было ясно ЧТО должно быть сделано.
Если взять ваш пример, то можно найти целую кучу низкоуровневых операций и приведений типов.
Если вы называете переменные не в шахматном стиле, e2 — e4, то это еще не делает ваш код самодокументируемым.
Например, метод MyFrame::loadHandlers(), можно разбить на несколько методов, для каждой магической операции в нем.
Методам — дать хорошие имена, которые говорят, что они делают, а не как.
Вот пример:
Магической операции вроде:
if (!dirHandlers.GetFirst( &sLibName, wxEmptyString, wxDIR_FILES)) return;
Дать имя, которое говорит, что же эта операция таки проверяет:
if (directoryIsEmpty(&sLibName, wxEmptyString, wxDIR_FILES)) return;
Честно говоря, этот текст от автора книги не укладывается у меня в голове. Я рассчитывал, что будет постепенный список того, что можно автоматизировать, несколько советов, по типу автоматизации рутины, может-быть создания своих плагинов для какого-нибудь софта…
Но тут: резкий скачек от “у нас ничего не автоматизировалось” до генерации кода на основе модели. Такой подход, конечно же существует, но я не скажу, что он настолько сильно распространен из-за сложности создания самой модели.
Если брать пример из главы, то мне кажется, легче будет 20 сайтов с корзиной, путь даже на собственном движке, наклепать, чем одну модель все это время разрабатывать.
Опять же, не ясна фраза с генерацией кода. Т.е., конечно же, во многих ситуациях, генерация части кода оправдана, как то создание UI интерфейсов или классы, декларирующие поля базы данных. Но, насколько я понял, автор хочет сгенерировать весь код приложения.
В формуле с рейтами программиста, явно рассматриваются какие-то предельные ситуации: “очень хороший и дорогой”, “дешевый и плохой”.
Будто-бы, посередине ничего нет. Я думаю, за рейт $45, можно вполне найти очень хорошего разработчика на просторах СНГ, так и в Индии (ведь, не все же там индокодят, просто тех, кто индокодит — большее число)
Execution of 1.pl aborted due to compilation errors.
Сама проблема кроется где-то в недрах .NET Framework.
Как последний из вариантов, которые у меня есть,
я прошу вас попробовать установить или обновить полный .NET Framework 4, который можно скачать по следующей ссылке:
www.microsoft.com/en-us/download/details.aspx?id=17718
Возможно, что у вас стоит урезанный Client Profile, в котором нет необходимой библиотеки.
Скачаю сегодня Win7 c modern.ie и попробую на ней.