code driven testing -- oleksandr pavlyshak
DESCRIPTION
IT Event 2011 SpringTRANSCRIPT
Agenda
• Поняття Unit test• Підміна залежностей, stubs• Тестування взаємодій, mocks• Якості хороших тестів• Unit vs integration testing• Практики• Метрики
Тестування
• Починається разом із розробкою• Запускаємо і дивимось• Створюємо допоміжні засоби– Консольні програми– Допоміжний UI
Unit test, визначення
• Код (зазвичай, метод)• Який викликає інший код• І після цього перевіряє правильність• Деяких припущень
• Unit = модуль, компонент • (функція, метод, клас, Unit of Work)
Unit test[TestFixture]public class CalculatorTests{ [Test] public void Sum_ReturnsCorrectValue() { var math = new Calculator();
int result = math.Sum(1, 2);
Assert.AreEqual(3, result); }}
Arrange/Act/Assert[TestFixture]public class CalculatorTests{ [Test] public void Sum_ReturnsCorrectValue() { var math = new Calculator(); // Arrange
int result = math.Sum(1, 2); // Act
Assert.AreEqual(3, result); // Assert }}
Єдиний assert/єдиний verify
• Юніт-тест повинен тестувати щось одне• Назва тесту важлива
[Test]public void Start_Test(){ var survey = new Survey();
survey.Start();
Assert.AreEqual(SurveyState.InProgress, survey.State); Assert.IsTrue(survey.FinishDate > survey.StartDate);}
Unit test framework
• Виконання тестів– Одного, декількох, всіх– Інтеграція з IDE
• API для написання тестів• Автоматизація• Перегляд результатів
Unit test framework
• NUnit, MS Test, MBUnit, DBUnit• JUnit, JWalk, TestNG, DBUnit• C++test, CppUnit, Google C++ Testing Fx• PyUnit
Continuous integration
Continuous integration
Залежності
DEMO[Test]public void Start_ChangesStateToInProgress(){ var survey = new Survey();
survey.Start();
Assert.AreEqual(SurveyState.InProgress, survey.State);}
Залежності
• Survey залежить від EmailSender• Не хочемо відсилати справжні листи• Створюємо stub вручну• Створюємо stub автоматично• Все ще тестуємо стан!
Assert.AreEqual(SurveyState.InProgress, survey.State);
Interaction testing
• Потреба тестувати взаємодії• Створюємо mock вручну• Створюємо mock автоматично• Один mock на тест• Тестуємо не стан, а взаємодію!
mockEmailSender.Verify();
Stubs + mocks
• Один тест – один mock• Декілька stubs
Fakes
Stubs 0..*
Mocks 0..1
Короткий підсумок
How unit testing helps
• Швидший цикл тестування коду• Коротший фідбек про можливі дефекти• Дефекти дешевші
Плюси тестів
• Кращий код• Стабільніша нова функціональність• Більше впевненості у змінах• Менше регресій• Коротші цикли релізів
Якості
Якості юніт тестів
• Readable• Maintainable• Trustworthy
Readable
• Легко зрозуміти, що відбувається в тесті• Який код тестується• Які передумови• Які припущення перевіряються• Що тестує тест• Простий код тесту
Trustworthy
• Релевантні до помилок• Стабільно (не) проходять• Немає конфліктуючих тестів• Справді тестують
Maintainable
• Тести легко реагують на зміни• Не вимагають конфігурації• Не залежать від інших тестів• Простий код тесту
Різновиди
Види тестів
• Юніт• Інтеграційні• Інші
Юніт тести
• Тестують один модуль• Виконуються виключно в пам’яті• Не вимагають конфігурації• Не вимагають DB, FS, AD, Net• Завжди– Повторювано проходять– Або повторювано не проходять– Тому що не залежать від змінних факторів
Інтеграційні тести
• Тестують модулі разом• Можуть мати різну поведінку• В залежності від– Середовища (FS, DB, AD, OS, .config)– Порядку виконання– Кількості виконання– Багатопоточності– Повного місяця
Інтеграційні тести -- Ознаки
• TearDown() • DateTime.Now• Thread• Environment.MachineName• Database.Save(…)• File.Open(…)
Mixing
• Чітке розділення UT та IT
Trustworthy
• Юніт-тести – ДОВІРА– Проходять --> мабуть немає дефекту– Не проходять --> точно є дефект
• Інтеграційні тести – (деколи) НЕДОВІРА– Проходять --> немає дефекту– Не проходять --> можливо дефект
Практики
Логіка в юніт-тестах
• Asserts in if/switch/for/while• Значно підвищується ймовірність появи
дефекта в тесті• Погіршується readability & maintainability
Дублювання логіки production коду
• Приклад• Tests last• Тест не тестує• Expected hardcoded values
Magic numbers
• Приклад • Найпростіші можливі значення• Оголошення і перевірка в тесті
Зміна тестів
• Створення:– У більшості випадків
• Видалення:– Коли тест більше не потрібний
• Редагування:– Для maintainability/readability– Для швидкості– Коли тест повинен виконуватись по-іншому
Тестувальник знаходить дефект
• Новий тест• Не повинен бути знайдений
тестувальниками знову
Що міряти
• Кількість регресій• Час виправлення дефектів• Метрики якості коду• People feedback• Покриття (coverage)
Обирайте усвідомлено
• Тестування не безкоштовне• Надмірність тестів• Надмірність тестів взаємодій• 100% покриття не завжди потрібне
На що дивитись далі
• Unit testing patterns• Mocks/stubs/fakes, isolation frameworks• TDD, Test Driven Development• Contracts, Contract Driven Development
Q&A
Code-driven testingОлександр Павлишак, [email protected]