Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
10 причин
моей ненависти
Andrei Solntsev
twitter.com/asolntsev
1. Пэджъ объжекты
2. Параллелизация
3. Параметризация
4. BDD
5. Красивые отчёты
6. TestNG
7. Оверинжиниринг
План
Чем плох
Пэдж обжект?
1/7
Пэдж обжект -
это хорошая идея
но
плохая практика
Классический пэдж обжект
@Test
public void googleSearch() {
GooglePage page = new GooglePage(webdriver);
page.setQuery("se...
Классический пэдж обжект
public class GooglePage {
@FindBy(name = “q”)
private WebElement queue;
public GooglePage(WebDriv...
Классический пэдж обжект
public class GooglePage {
@FindBy(name = “q”)
private WebElement queue;
public GooglePage(WebDriv...
Selenide пэдж обжект
public class GooglePage {
public void search(String query) {
$(By.name(“q”))
.val(queue)
.pressEnter(...
Чем плох
@FindBy?
Чем плох @FindBy?
public class MyPage {
@FindBy(xpath = "//div[1]/div[2]/input[@name=bd]")
public WebElement birthday;
}
@...
если изменится локатор,
придётся поменять только в одном месте.
но
меняется не только локатор.
Меняется поведение.
типа
Что, если изменится не это:
public class MyPage {
@FindBy(xpath = "//div[1]/div[2]/input[@name=bd]")
public WebElement bir...
А вот это:
public class MyPage {
@FindBy(xpath = "//div[1]/div[2]/input[@name=bd]")
public WebElement birthday;
}
@Test {
...
данные и операции с ними.
Объект - это поведение.
Объект - это НЕ
Настоящие пэдж-объекты
Решение: поля -> методы
public class MyPage {
public void selectBirthday(String date) {
...
}
}
@Test {
page.selectBirthda...
Можно приватное поле с @FindBy:
public class MyPage {
@FindBy(xpath = "//div[1]/div[2]/input[@name=bd]")
private WebElemen...
Можно приватное поле By:
public class MyPage {
private By birthday = By.xpath(“...”);
public void selectBirthday(String da...
Можно приватное поле String:
public class MyPage {
private String birthday = “input[name=bday]”;
public void selectBirthda...
А можно...
ой, божечки!..
вообще без поля.
public class MyPage {
public void selectBirthday(String date) {
$(“#birthday”).sendKeys(date);
}
}
А что,
так можно было?
Какие проблемы должен решать ПО
Плохие локаторы1.
public class MyPage {
@FindBy(xpath = "//div[1]/div[2]/input[@name=bd]")...
Какие проблемы должен решать ПО
2.
Плохие локаторы1.
Дублирование локаторов
Но эти проблемы -
следствия
плохого процесса
Плохой процесс:
● Разрабы не пишут тесты
○ Нет юнит-тестов
● Через UI тестируется много кейсов
○ (но далеко не все!)
● Тес...
При правильном процессе:
Плохие
локаторы
1. ● Разрабы делают
хорошие локаторы
public class MyPage {
WebElement birthday = ...
При правильном процессе:
2.
Плохие
локаторы
1.
Дублирование
локаторов
● Разрабы делают
хорошие локаторы
● Большинство кейс...
Поговори с разрабом!
В чём он заинтересован?
● Он не любит получать по рукам
● Он не хочет, чтобы его фича сломалась
● Он ...
Поговори с разрабом!
В чём он заинтересован?
● Он не любит получать по рукам
● Он не хочет, чтобы его фича сломалась
● Он ...
Пэдж обжекты -
техническое решение
для
нетехнической проблемы
А это всегда плохая идея!
Чем плоха
параллелизация?
2/7
Снова плохой процесс
● Нет юнит-тестов
● UI-тестами покрываются многие комбинации
○ Сложные сценарии
○ Медленные сценарии
...
●
Снова плохой процесс
● Нет юнит-тестов
● UI-тестами покрываются многие комбинации
○ Сложные сценарии
○ Медленные сценари...
При правильном процессе:
● Юнит-тестов много
● UI-тестов мало
● Они бегут быстро
Экономически эффективный
процесс тестиров...
Чак Норрис
не параллелит тесты
Они и в одном потоке быстро бегут
Чак Норрис
не параллелит тесты
Чак Норрис
ПЕРПЕНДИКУЛЯРИТ тесты!
Параллелить, конечно, можно,
если всё остальное решено:
14 часов -> 3 часа
не норм!
40 минут -> 10
норм!
Чем плохи
параметризированные
тесты?
3/7
Болезнь индустрии
-
Слишком много через UI тесты
а
параметризированные тесты
делают это проще
Параметризированные тесты
:
Для UI-тестов
плохо!
Для unit-тестов
хорошо!
Чем плох
BDD?
4/7
BDD -
это офигенная идея
но
она не работает
BDD - это
язык для
заказчика и исполнителя
взаимодействия
(в теории)
BDD - это
отчёты с картинками
заказчик не читает
которые
(на практике)
Это не про тесты
Это про разработку
Это не про отчёты
Это про взаимодействие
с заказчиком
BDD
Bullshit driven development
BDD обещает Красивые отчёты
Менеджер надеется
решить
Отсутствие доверия к команде.
Непрозрачный рабочий процесс.
Решает ли...
BDD обещает Красивые отчёты
Менеджер надеется
решить
Показать своему боссу /
заказчику, что "у нас всё круто",
работа кипи...
BDD обещает
тесты смогут писать даже
нетехнические люди
Менеджер надеется
решить
Технарей мало, они всё не
успевают. Хочет...
Что
не так
с отчётами? 5/7
● отчёт JUnit/TestNG - достаточно хорош
● Selenide добавляет скриншот+html
Element should be hidden {#gameWin}
Element: '<...
Что не так с
TestNG? 6/7
Разница между JUnit и TestNG
JUnit TestNG
Новый инстанс перед
каждым тестом
Один инстанс на все
тест-методы
JUnit pain
JUnit TestNG
Created MyTest
Created MyTest
Created MyTest
public class MyTest {
public MyTest() {
System.out.println(“Crea...
JUnit TestNG
public class MyTest {
Foo foo = mock(Foo.class);
Counter cnt = new Counter(0);
}
public class MyTest {
Foo fo...
Фичи TestNG
● Конфигурация в XML
● Порядок тестов
● Зависимые тесты
(которых нет в JUnit)
Эти фичи - ЗЛО!
Не используй их,...
TestNG
“Не хочешь злые фичи - не используй.
Никто ж не заставляет.”
Бог с вами, хотите - используйте TestNG.
Но не называйте его “тулом для продвинутого
интеграционного тестирования”.
Он для...
Беда IT -
оверинжиниринг!
7/7
Оверинжиниринг
protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) {
int attempts = 0;
while (...
Оверинжиниринг
protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) {
int attempts = 0;
while (...
Оверинжиниринг
protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) {
int attempts = 0;
while (...
KISS
protected void waitForElementClickable(By locator, int timeout) {
new WebDriverWait(driver, timeout).until(condition)...
KISS by Selenide
$(locator).click();
$(locator).shouldBe(visible).click();
$(locator).waitUntil(visible, 30_000).click();
Винтовка -
Выбор профессионала -
Оружие новичка.
НОЖ!
Самая опасная идея
та,
которая кажется хорошей.
Douglas Crockford
JavaScript: The Good Parts
Андрей Солнцев
@asolntsev
ru.selenide.org
Больше видео
Спасибо за фотки:
1. https://stories.genvagula.com/my-magical-estonia-500aafd5b2c0
2. https://www.facebook.com/stan.vasily...
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти
Prochain SlideShare
Chargement dans…5
×

QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти

243 vues

Publié le

Меня часто спрашивают, за что я не люблю в тестах Page Objects, TestNG, ReportPortal, try/catch, циклы и условия, неявные ожидания, явные ожидания, Dependency injection, Spring и т.д.
Расскажу коротко и быстро. На каждую тему 5 минут.

Publié dans : Formation
  • Soyez le premier à commenter

QA Fest 2019. Андрей Солнцев. Десять причин моей ненависти

  1. 1. 10 причин моей ненависти Andrei Solntsev twitter.com/asolntsev
  2. 2. 1. Пэджъ объжекты 2. Параллелизация 3. Параметризация 4. BDD 5. Красивые отчёты 6. TestNG 7. Оверинжиниринг План
  3. 3. Чем плох Пэдж обжект? 1/7
  4. 4. Пэдж обжект - это хорошая идея но плохая практика
  5. 5. Классический пэдж обжект @Test public void googleSearch() { GooglePage page = new GooglePage(webdriver); page.setQuery("selenide"); page.submitQuery(); }
  6. 6. Классический пэдж обжект public class GooglePage { @FindBy(name = “q”) private WebElement queue; public GooglePage(WebDriver webdriver) { PageFactory.initElements(webdriver, this); } public void setQuery(String query) { queue.clear(); queue.sendKeys(query); }
  7. 7. Классический пэдж обжект public class GooglePage { @FindBy(name = “q”) private WebElement queue; public GooglePage(WebDriver webdriver) { PageFactory.initElements(webdriver, this); } public void setQuery(String query) { queue.clear(); queue.sendKeys(query); } Бойлерплейт!
  8. 8. Selenide пэдж обжект public class GooglePage { public void search(String query) { $(By.name(“q”)) .val(queue) .pressEnter(); } }
  9. 9. Чем плох @FindBy?
  10. 10. Чем плох @FindBy? public class MyPage { @FindBy(xpath = "//div[1]/div[2]/input[@name=bd]") public WebElement birthday; } @Test { MyPage page = new MyPage(webdriver); birthday.sendKeys("19.03.1955"); }
  11. 11. если изменится локатор, придётся поменять только в одном месте. но меняется не только локатор. Меняется поведение. типа
  12. 12. Что, если изменится не это: public class MyPage { @FindBy(xpath = "//div[1]/div[2]/input[@name=bd]") public WebElement birthday; } @Test { MyPage page = new MyPage(webdriver); birthday.sendKeys("19.03.1955"); }
  13. 13. А вот это: public class MyPage { @FindBy(xpath = "//div[1]/div[2]/input[@name=bd]") public WebElement birthday; } @Test { MyPage page = new MyPage(webdriver); birthday.sendKeys("19.03.1955"); } 1. Открыть календарь 2. Выбрать год 3. Выбрать месяц... Упс! Придётся менять кучу тестов.
  14. 14. данные и операции с ними. Объект - это поведение. Объект - это НЕ Настоящие пэдж-объекты
  15. 15. Решение: поля -> методы public class MyPage { public void selectBirthday(String date) { ... } } @Test { page.selectBirthday("19.03.1955"); } ● Публичный только метод ● Внутри - делай что хочешь Это инкапсуляция, братан!
  16. 16. Можно приватное поле с @FindBy: public class MyPage { @FindBy(xpath = "//div[1]/div[2]/input[@name=bd]") private WebElement birthday; public void selectBirthday(String date) { ... } }
  17. 17. Можно приватное поле By: public class MyPage { private By birthday = By.xpath(“...”); public void selectBirthday(String date) { $(birthday).sendKeys(date); } }
  18. 18. Можно приватное поле String: public class MyPage { private String birthday = “input[name=bday]”; public void selectBirthday(String date) { $(birthday).sendKeys(date); } }
  19. 19. А можно... ой, божечки!.. вообще без поля.
  20. 20. public class MyPage { public void selectBirthday(String date) { $(“#birthday”).sendKeys(date); } } А что, так можно было?
  21. 21. Какие проблемы должен решать ПО Плохие локаторы1. public class MyPage { @FindBy(xpath = "//div[1]/div[2]/input[@name=bd]") private WebElement birthday; }
  22. 22. Какие проблемы должен решать ПО 2. Плохие локаторы1. Дублирование локаторов
  23. 23. Но эти проблемы - следствия плохого процесса
  24. 24. Плохой процесс: ● Разрабы не пишут тесты ○ Нет юнит-тестов ● Через UI тестируется много кейсов ○ (но далеко не все!) ● Тесты медленные & нестабильные ○ (хотим отчёты и рипортпорталы) ● QA не сотрудничают с разрабами Экономически эффективный процесс тестирования
  25. 25. При правильном процессе: Плохие локаторы 1. ● Разрабы делают хорошие локаторы public class MyPage { WebElement birthday = $(“#birthday”); } ПО больше не такой уж ценный:
  26. 26. При правильном процессе: 2. Плохие локаторы 1. Дублирование локаторов ● Разрабы делают хорошие локаторы ● Большинство кейсов покрыто юнит-тестами. ● UI-тестами покрывается только один-два сценария ● Каждый локатор используется мало"Пацан накодил - пацан протестил!"
  27. 27. Поговори с разрабом! В чём он заинтересован? ● Он не любит получать по рукам ● Он не хочет, чтобы его фича сломалась ● Он не мечтает фиксить багу все выходные
  28. 28. Поговори с разрабом! В чём он заинтересован? ● Он не любит получать по рукам ● Он не хочет, чтобы его фича сломалась ● Он не мечтает фиксить багу все выходные Крошка Енот Вы можете помочь друг другу!
  29. 29. Пэдж обжекты - техническое решение для нетехнической проблемы А это всегда плохая идея!
  30. 30. Чем плоха параллелизация? 2/7
  31. 31. Снова плохой процесс ● Нет юнит-тестов ● UI-тестами покрываются многие комбинации ○ Сложные сценарии ○ Медленные сценарии ○ Трудновоспроизводимые сценарии ● Testability на дне ○ Медленный тестовый стенд ● Тесты бегут 12 часов
  32. 32. ● Снова плохой процесс ● Нет юнит-тестов ● UI-тестами покрываются многие комбинации ○ Сложные сценарии ○ Медленные сценарии ○ Трудновоспроизводимые сценарии ● Testability на дне ○ Медленный тестовый стенд ● Почему бы не запустить параллельно? ● В 100500 потоков? ● Ферма, йопта! ● Клауд, йопта! ● TestNG, йопта! ● Я теперь SDET, йопта!
  33. 33. При правильном процессе: ● Юнит-тестов много ● UI-тестов мало ● Они бегут быстро Экономически эффективный процесс тестирования Test Pyramid
  34. 34. Чак Норрис не параллелит тесты Они и в одном потоке быстро бегут
  35. 35. Чак Норрис не параллелит тесты Чак Норрис ПЕРПЕНДИКУЛЯРИТ тесты!
  36. 36. Параллелить, конечно, можно, если всё остальное решено: 14 часов -> 3 часа не норм! 40 минут -> 10 норм!
  37. 37. Чем плохи параметризированные тесты? 3/7
  38. 38. Болезнь индустрии - Слишком много через UI тесты а параметризированные тесты делают это проще
  39. 39. Параметризированные тесты : Для UI-тестов плохо! Для unit-тестов хорошо!
  40. 40. Чем плох BDD? 4/7
  41. 41. BDD - это офигенная идея но она не работает
  42. 42. BDD - это язык для заказчика и исполнителя взаимодействия (в теории)
  43. 43. BDD - это отчёты с картинками заказчик не читает которые (на практике)
  44. 44. Это не про тесты Это про разработку
  45. 45. Это не про отчёты Это про взаимодействие с заказчиком BDD Bullshit driven development
  46. 46. BDD обещает Красивые отчёты Менеджер надеется решить Отсутствие доверия к команде. Непрозрачный рабочий процесс. Решает ли BDD эту проблему? Нет. Доверия как не было, так и нет. BDD: Болезни vs. симптомы
  47. 47. BDD обещает Красивые отчёты Менеджер надеется решить Показать своему боссу / заказчику, что "у нас всё круто", работа кипит. Какая проблема на самом деле Этот менеджер - промежуточный человек, ничего полезного в проект не привносит. Решает ли BDD эту проблему? Нет. Гнать таких в шею - вот решение.
  48. 48. BDD обещает тесты смогут писать даже нетехнические люди Менеджер надеется решить Технарей мало, они всё не успевают. Хочется часть работы переложить на гуманитариев. Решает ли BDD эту проблему? Нет. Вся работа по поддержке степов и прочей БелиБерДы по-любому ложится на плечи технарей.P.S. Кстати, толковых гуманитариев тоже мало. А бестолковые только мешают.
  49. 49. Что не так с отчётами? 5/7
  50. 50. ● отчёт JUnit/TestNG - достаточно хорош ● Selenide добавляет скриншот+html Element should be hidden {#gameWin} Element: '<img class="gameOver" id="gameWin" src="img/thumbs-up.jpeg"></img>' Screenshot: file:/.../hangman/build/reports/tests/1510751914648.0.png Page source: file:/.../hangman/build/reports/tests/1510751914648.0.html Timeout: 4 s. Этого достаточно!
  51. 51. Что не так с TestNG? 6/7
  52. 52. Разница между JUnit и TestNG JUnit TestNG Новый инстанс перед каждым тестом Один инстанс на все тест-методы JUnit pain
  53. 53. JUnit TestNG Created MyTest Created MyTest Created MyTest public class MyTest { public MyTest() { System.out.println(“Created MyTest”); } @Test public void testA() {} @Test public void testB() {} @Test public void testC() {} } Created MyTest
  54. 54. JUnit TestNG public class MyTest { Foo foo = mock(Foo.class); Counter cnt = new Counter(0); } public class MyTest { Foo foo; Counter cnt; @BeforeEach public void setUp() { foo = mock(Foo.class); cnt = new Counter(0); } } Почему это важно? Риск зависимых тестов!
  55. 55. Фичи TestNG ● Конфигурация в XML ● Порядок тестов ● Зависимые тесты (которых нет в JUnit) Эти фичи - ЗЛО! Не используй их, братан!
  56. 56. TestNG “Не хочешь злые фичи - не используй. Никто ж не заставляет.”
  57. 57. Бог с вами, хотите - используйте TestNG. Но не называйте его “тулом для продвинутого интеграционного тестирования”. Он для неэффективного, неуправляемого, медленного, нестабильного интеграционного тестирования. Arrange, mazafaka!
  58. 58. Беда IT - оверинжиниринг! 7/7
  59. 59. Оверинжиниринг protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) { int attempts = 0; while (attempts < 2) { try { waitFor(elementToBeClickable(locator), (timeOutInSeconds.length > 0 ? timeOutInSeconds[0] : null)); break; } catch (StaleElementReferenceException e) { } attempts++; } void waitFor(ExpectedCondition<WebElement> condition, Integer timeOutInSeconds) { timeOutInSeconds = timeOutInSeconds != null ? timeOutInSeconds : 30; WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); wait.until(condition); }
  60. 60. Оверинжиниринг protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) { int attempts = 0; while (attempts < 2) { try { waitFor(elementToBeClickable(locator), (timeOutInSeconds.length > 0 ? timeOutInSeconds[0] : null)); break; } catch (StaleElementReferenceException e) { } attempts++; } void waitFor(ExpectedCondition<WebElement> condition, Integer timeOutInSeconds) { timeOutInSeconds = timeOutInSeconds != null ? timeOutInSeconds : 30; WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); wait.until(condition); }
  61. 61. Оверинжиниринг protected void waitForElementClickable(By locator, Integer... timeOutInSeconds) { int attempts = 0; while (attempts < 2) { try { waitFor(elementToBeClickable(locator), (timeOutInSeconds.length > 0 ? timeOutInSeconds[0] : null)); break; } catch (StaleElementReferenceException e) { } attempts++; } void waitFor(ExpectedCondition<WebElement> condition, Integer timeOutInSeconds) { timeOutInSeconds = timeOutInSeconds != null ? timeOutInSeconds : 30; WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); wait.until(condition); }
  62. 62. KISS protected void waitForElementClickable(By locator, int timeout) { new WebDriverWait(driver, timeout).until(condition); } protected void waitForElementClickable(By locator) { waitForElementClickable(locator, 30); } : Keep it scuko simple!
  63. 63. KISS by Selenide $(locator).click(); $(locator).shouldBe(visible).click(); $(locator).waitUntil(visible, 30_000).click();
  64. 64. Винтовка - Выбор профессионала - Оружие новичка. НОЖ!
  65. 65. Самая опасная идея та, которая кажется хорошей. Douglas Crockford JavaScript: The Good Parts
  66. 66. Андрей Солнцев @asolntsev ru.selenide.org Больше видео
  67. 67. Спасибо за фотки: 1. https://stories.genvagula.com/my-magical-estonia-500aafd5b2c0 2. https://www.facebook.com/stan.vasilyev 3. https://i-love-tallinn.livejournal.com/306474.html 4. https://www.facebook.com/lyosha.razin 5. https://www.facebook.com/ttrk19/

×