Знакомо ощущение, когда смотрите на код, тест-кейc или на процесс - "здесь что-то не так"? Значит вы уловили этот запах - "test smells". К сожалению, не всегда понятно - от чего же он, и даже больше - что с ним делать. Непонимание, и как следствие, неверное применение хороших практик, собственные адаптации и приводят ошибкам, сложностям и еще большему усугублению проблемы.
В этом докладе, я поделюсь с вами своими мыслями и опытом. Как выглядят популярные проблемы, антипаттерны и запахи. Как их различить и что сделать, чтобы избавиться от них.
2. О себе
Follow me on Fb
https://www.facebook.com/gr
oups/1180099188730673/
Иван Пашко
● Scrum Master
● QA Automation Engineer
● 9+ лет в ИТ
● 0+ лет счастливый отец
3. Антипаттерны и запахи тестов
◎Личный опыт
◎Собеседования!
◎Форумы Соц. Сети
◎Конференции митапы
5. Что такое анти-паттерн?
Анти-паттерн - это распространенный
подход к решению класса часто
встречающихся проблем, являющийся
неэффективным, рискованным или
непродуктивным.
13. Что такое запах теста?
Тест (код) с запашком - термин,
обозначающий признаки (запахи)
проблем в системекодесценарие.
Ключевые признаки необходимости
рефакторинга.
14. #1 Неясный тест (Obscure test)
Тест, который трудно понять с первого
взгляда.
15. #2 Мучительный тест (Eager test)
public void MakeVisaPayment()
{
// Create customer
var customer = new Customer();
Assert.IsNotNull(customer);
// Configure method
var visaMethod = new PaymentMethod("VISA") {
Limits = new Limits(5, 1000, "USD");
SetConfigurationGateway = "https://payment.visa.com";
};
Assert.IsTrue(visaMethod.GatewayPingIsOk());
// Link customer to method
customer.AssignPaymentMethod(visaMethod);
// MakePayment
var result = customer.ProcessPayment( 100, "USD", "VISA");
//Check status
Assert.AreEqual("OK", result.Status);
}
Вроде как проверка возможности платежа визой
Зачем тогда эти проверки?
16. public void CheckVisaGatewayConfiguration()
{
// Create customer
var customer = new Customer();
Assert.IsNotNull(customer);
// Configure method
var visaMethod = new PaymentMethod("VISA") {
Limits = new Limits(5, 1000, "USD");
SetConfigurationGateway = "https://payment.visa.com";
};
Assert.IsTrue(visaMethod.GatewayPingIsOk());
// Link customer to method
customer.AssignPaymentMethod(visaMethod);
// MakePayment
var result = customer.ProcessPayment( 100, "USD", "VISA");
//Check status
Assert.AreEqual("OK", result.Status);
}
#2 Мучительный тест (Eager test)
А зачем тогда эта
проверка?
17. #3 Однострочный тест (Mystery Guest)
[TestMethod]
public void CheckVisaPayment()
{
DoPaymentTest("VISA");
}
[TestMethod]
public void CheckMasterCardPayment()
{
DoPaymentTest("MasterCard");
}
18. #4 Тест с ветвлениями
[TestMethod]
public void CheckPaymentChargeback()
{
var ppid = DoPaymentTest("VISA");
if (string.IsNullOrEmpty(ppid))
{
MakePaymentRefund("VISA");
}
}
19. Хороший тест - это баланс кода и
документирования
// Arrange
var result = new DepositFlow()
.ByMethod("VISA")
.WithCreditCard("4111 1111 1111 1111")
.WithAmount(100, "UAH")
// Act
.Submit();
// Assert
Assert.AreEqual("OK",
result.Status);
22. #5.2 Комментарии - плохо
// Строка для поиска
const string tmp = "I want to join QAFest";
// Инициализация драйвера, не забудьте потом закрыть сессию
var driver = new ChromeDriver();
// Переход на сайт-поисковик
driver.Navigate().GoToUrl(new Uri("https://www.google.com.ua"));
// Ввод в строку поиска
driver.FindElement(OpenQA.Selenium.By.Name("q")).SendKeys( …
// Нажатие кнопки поиска
driver.FindElement(OpenQA.Selenium.By.Name("btnK")).Click();
23. #5.2 Комментарии - хорошо
// Arrage
const string SEARCH_STRING = "I want to join QAFest2017";
// Act
var googlePage = new SearchPage()
.WithUrl("https://www.google.com.ua");
var firstResult = googlePage.DoSearch(SEARCH_STRING).First();
// Assert
Assert.AreEqual("qafest.com", firstResult);
24. #6 Код про запас, на будущее
Пишем, и оставляем неиспользуемый код,
авось когда-то пригодится
27. #9 Запахи в тестовых проверках
Основа теста - его проверки
28. #9.1 Множественные проверки
//Проверяем Int32
Assert.IsTrue(Int32.TryParse("1", out n));
Assert.AreEqual(1, Int32.Parse("1"));
Assert.IsTrue(Int32.TryParse("-1", out n));
Assert.AreEqual(-1, Int32.Parse("-1"));
....
//Мульти-проверки NUnit
Assert.Multiple(() =>
{
Assert.IsTrue(Int32.TryParse("-1", out n));
Assert.AreEqual(-1, Int32.Parse("-1"));
});
А если мы упадем
тут. Надо заново
запускать тест...
29. #9.2 Запутанная проверка
[TestMethod]
public void TestInt32Parser()
…
Assert.IsTrue(Int32.TryParse("1", out n));
Assert.AreEqual(1, Int32.Parse("1"));
//Граничные значения
Assert.IsTrue(Int32.TryParse("2147483648", out n));
Assert.AreEqual(2147483648, Int32.Parse("2147483648"));
//Переполнение буфера
Assert.IsFalse(Int32.TryParse("2147483649", out n));
Assert.AreEqual(-2147483648, Int32.MaxValue + 1);
Интересно, что
же проверяет
этот тест..
30. #9.3 Условная проверка
// Assert
if (searchResults.Count > 0)
{
Assert.AreEqual("http://qafest.com/", searchResults.First( …
}
else
{
var notFoundElm = driver.FindElement(OpenQA.Selenium.By.Id( …
Assert.AreEqual("По запросу ничего не найдено. ", notFoundE …
}
За почти 10 лет в ИТ, я участвовал в различных проектах на разных позициях. Организовывал процессы или занимался сугубо автоматизацией. Разрабатывал с нуля или оптимизировал существующее решение - вобщем было много различных процессов, решений, выборов.
Хорошие практики - это хорошо, но также хорошие практики - это специфика, специфика конкретного применения в конкретной ситуации. Я же сегодня с вами хочу обсудить обратную сторону хороших практик - антипаттерны, или плохие практики.
Начать:
Все события и герои вымышлены. Любые совпадения с реальными личностями случайны.
Не все истории случались со мной на проектах
Много историй я почерпнул с историй на собеседованиях.
Собеседования - как исповедь, зачастую жалуемся на то как плохо было и как хорошо кому-то не разрешали сделать.
Я попытался организовать все идеи вместе, и чтобы поделится с ними сегодня с вами.
Итак, начнем, поговорим об анти-паттернах.
Не просто антипатернах - а больше о процессе автоматизации и ее применению
Это анти-практики, подходы, которые приносят больше вреда чем пользы.
Не значит что так делать неправильно и никогда-никогда не нужно
Все зависит от ситуации.
Зачастую это просто неверное применение хорошей практики.
Пример - микроскопом гвозди забивать
Не надо воспринимать презентацию как неоспоримую истину - больше как возможность взглянуть со стороны и подумать, ваше решение приносит вам больше вреди или пользы
Возникает все от из 3х направлений.
Отсутствие желания, отсутствие знания или отсутствие времени.
Или амбиции
С третим пунктом возможно я и помогу сегодня- остальные - точно лягут на ваши плечи
изоляция автоматизации от процессов (разработки или тестирования.)
Это пункт №1 - из услышанного на собеседованиях. Каждый второй рассказывал подобную историю:
Берем тесткейзы и автоматизируем.
А дальше?
А дальше они автоматизированы, берем следующие :)
Отсутствие коммуникации между командами
Какой профит от такой автоматизации?
Забываем - Цель любого действия - польза. Изоляция не приносит пользы
Что делать?
Если у вас есть отдел мануальніх тестировщиков, или отдельній стенд с тест-кейзами, или сценариями - обязательно линкуйте автоматизацию к ним
А еще лучше - синхронизируйте. Это очень актуально, если у вас распределенные команды.
ИСТОРИЯ:
“Как проходит жизненный цикл разработки ваших тестов? Вы получаете задачу на тест, выполняете его, вводите в консоли пару команд (или пару хот-клеев), после чего сборка запуска поётся на удаленном сервере, прогоняются все тесты, вам на почту приходит отчёт о результатах, ещё пара команд и pull request на ревью уже у вашего коллеги и задача готова идти в мастер, мануальный тесткецзы в ТМжм системе помечаются пройденными.
Если не так, у вас есть отличная возможность заняться автоматизацией :) ведь этилен только написание тестов, помните, это инструмент
ЧТО ОБЫЧНО ЕСТЬ (ТОЧНЕЕ ЧЕГО НЕТ)
Наличие мануальной поддержки процесса автоматизации:
Ручной запуск тестов
Отсутствие нотификации о состоянии (надо самому смотреть)
Авто сборка-апдейт енвайромента
Отсутствие синхронизации с тест-кейзами (если есть такие)
Генерация данных
Автоматизация это инструмент QA.
Создание сценария - часть процесса, (мануальная часть!)
Автоматизация не отвечает за качество, покрытие (для этого етсь тест-стратегии\тест-планы)
Тестирование это процесс -
и автоматизация его составляющая.
https://automationrocks.wordpress.com/2015/02/04/automation-anti-patterns-myths-exposed/
Вот он как-раз возникает из-за 4 пункта - амбиций.
Мы инженеры - для нас решение задачи - это наркотик, и всегда хочется больше.
Когда это больше идёт во вред - оно становиться антипаттерном
Подружите автоматизацию и тестирование!
Плавно переходим от процессуальных штук к более близким нам - а именно кодингу.
Это анти-практики, подходы, которые приносят больше вреда чем пользы. Это не значит что так делать неправильно и никогда-никогда не нужно - все зависит от ситуации. Неверное или ненужное применение хорошей практики делает ее плохой.
Отличается от код-смелл. В первую очередь тест это тест, а уже потом -код
Automated tests should serve at least two purposes. First, they should act as documentation of how the system under test (SUT) should behave
Перекладываем ответственность на инициализацию
Нет читаемости
Тяжело мейнтейнить
А начнем мы с самой базовой - это дубликаты.
Дубликация кода - надо выносить в методы
Дубликация тестового сценария
Если так нравится писать комментарии - используйте лучше BDD
Если так нравится писать комментарии - используйте лучше BDD
А начнем мы с самой базовой - это дубликаты.
Дубликация кода - надо выносить в методы
Дубликация тестового сценария
Shared changeable fixture
Not isolated local fixtures
Один тест меняет данные - нельзя ранить параллельно.
Когда в тесте (в тестовой фикстуре) описано больше чем в самом тесте. Там все запутано, непонятно. Код создания - функциональный (вызываются методы), а не сетит состояние
Сложная логика создания
Поговорим о ассертах. Часті вопрос - сколько может біть ассертов - и вроде как для автоматизации(не юнит тестов) более одного аасерта уже не считается плохой практикой
Это да, но есть нюанс
Неплохой пример плохих тестов https://www.techwell.com/techwell-insights/2015/09/test-design-automation-anti-patterns
Silent assert http://nomoretesting.com/2016/05/23/anti-patterns/
Over-Checking: Checks not relevant for the scope. Since test designers often follow an approach of steps with an expected result for each step, tests do many checks that do not fit the scope of such tests. Such checks are unnecessary and probably over-lapping similar checks elsewhere. They then clutter up result statistics (e.g. they create too many “passes”), and aggravate the impact of changes in the application under test.
Sneaky Checking: Checks hidden in actions. Even though it is good to have business level actions that hide unneeded details for many of the tests, try to avoid hiding too much. In particular, checks should be explicit and visible in the main test (the test modules), at the appropriate level of detail. An outsider should be able to understand what is being tested by just looking at the test module, without a need to inspect how actions are implemented.
Как ві думаете, какой тест прошел? Нашел ли гугл мне информацию по QAFest?
Неплохой пример плохих тестов https://www.techwell.com/techwell-insights/2015/09/test-design-automation-anti-patterns
Silent assert http://nomoretesting.com/2016/05/23/anti-patterns/
Читабельный
Надежный в эксплуатации \ поддержке
Пригодный и удобный в использовании
Гибкий