Automated Testing
Про тестування
• Тестування не підвищує якість ПЗ,
• а сприяє розпізнаванню неправильної
  поведінки,
• завдяки чому розробники можуть знайти
  помилки і виправити їх
• Тестування не може довести відсутності
  дефектів
  – Лише їх наявність
• В будь-якій програмі є дефекти
Тестування
• Починається разом із розробкою
• Спосіб: запускаємо і дивимось чи працює
• Створюємо допоміжні засоби
  – Консольні програми
  – Допоміжний UI
Unit test, визначення
•   Код (зазвичай, метод)
•   Який викликає інший код
•   І після цього перевіряє правильність
•   Деяких припущень

• Unit = модуль, компонент
• (функція, метод, клас, Unit of Work)
Unit test framework
• Виконання тестів
  – Одного, декількох, всіх
  – Інтеграція з IDE
• API для написання тестів
• Автоматизація
• Перегляд результатів
Unit test framework
• NUnit, MS Test, Xunit, MBUnit, DBUnit
• Test runners:
  – Visual Studio, NUnit GUI/Console apps,
    ReSharper, TestDriven.Net, Gallio
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
    }
}
Що тестувати
• Код, що містить логіку
    private DateTime _startDate;

    // doesn’t need to be tested
    public DateTime StartDate
    {
        get { return _startDate; }
        set { _startDate = value; }
    }
Єдиний assert
• Юніт-тест повинен тестувати щось одне
• Назва тесту важлива
[Test]
public void Start_Test()
{
    var survey = new Survey();

    survey.Start();

    Assert.AreEqual(SurveyState.InProgress, survey.State);
    Assert.IsTrue(survey.FinishDate > survey.StartDate);
}
Залежності
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();
Особливості тестів на поведінку
• Реалізують
  діаграми послідовності
  (sequence diagram)
• Дозволяють розробляти
  “згори вниз”
• отримуючи API “нижчих” об’єктів
  “автоматично”
Stubs + mocks
• Один тест – один mock
• Декілька stubs

                 Fakes


        Stubs             Mocks
         0..*              0..1
Короткий підсумок
How unit testing helps
• Швидший цикл тестування коду
• Коротший фідбек про можливі дефекти
• Дефекти дешевші
Плюси тестів
•   Кращий код
•   Стабільніша нова функціональність
•   Більше впевненості у змінах
•   Менше регресій
•   Коротші цикли релізів
Різновиди
Види тестів
• Юніт
• Інтеграційні
• Інші
Юніт тести
•   Тестують один модуль
•   Виконуються виключно в пам’яті
•   Не вимагають конфігурації
•   Не вимагають DB, FS, AD, Net
•   Завжди
    – Повторювано проходять
    – Або повторювано не проходять
    – Тому що не залежать від змінних факторів
Інтеграційні тести
• Тестують модулі разом
• Можуть мати різну поведінку
• В залежності від
  – Середовища (FS, DB, AD, OS, .config)
  – Порядку виконання
  – Кількості виконання
  – Багатопоточності
  – Повного місяця
Інтеграційні тести -- Ознаки
•   TearDown()
•   DateTime.Now
•   Thread
•   Environment.MachineName
•   Database.Save(…)
•   File.Open(…)
Структура проекту
• Чітке розділення UT та IT
Trustworthy
• Юніт-тести – ДОВІРА
  – Проходять --> мабуть немає дефекту
  – Не проходять --> точно є дефект
• Інтеграційні тести – (деколи) НЕДОВІРА
  – Проходять --> немає дефекту
  – Не проходять --> можливо дефект
Практики
Якщо в коді помилка, тести
     повинні це показувати
• Спосіб перевірки – внести помилку і
  перевірити, як тести про це сповіщають
Логіка в юніт-тестах
• Asserts in if/switch/for/while
• Значно підвищується ймовірність появи
  дефекта в тесті
• Погіршується readability & maintainability
Дублювання логіки production коду
•   Приклад
•   Tests last
•   Тест не тестує
•   Expected hardcoded values
Magic numbers
• Приклад
• Найпростіші можливі значення
• Оголошення і перевірка в тесті
Зміна тестів
• Створення:
  – У більшості випадків
• Видалення:
  – Коли тест більше не потрібний
• Редагування:
  – Для maintainability/readability
  – Для швидкості
  – Коли тест повинен виконуватись по-іншому
Тестувальник знаходить дефект
• Пишемо новий тест
• Дефект не повинен бути знайдений
  тестувальниками знову
Questions

Automated testing

  • 1.
  • 2.
    Про тестування • Тестуванняне підвищує якість ПЗ, • а сприяє розпізнаванню неправильної поведінки, • завдяки чому розробники можуть знайти помилки і виправити їх • Тестування не може довести відсутності дефектів – Лише їх наявність • В будь-якій програмі є дефекти
  • 3.
    Тестування • Починається разоміз розробкою • Спосіб: запускаємо і дивимось чи працює • Створюємо допоміжні засоби – Консольні програми – Допоміжний UI
  • 4.
    Unit test, визначення • Код (зазвичай, метод) • Який викликає інший код • І після цього перевіряє правильність • Деяких припущень • Unit = модуль, компонент • (функція, метод, клас, Unit of Work)
  • 5.
    Unit test framework •Виконання тестів – Одного, декількох, всіх – Інтеграція з IDE • API для написання тестів • Автоматизація • Перегляд результатів
  • 6.
    Unit test framework •NUnit, MS Test, Xunit, MBUnit, DBUnit • Test runners: – Visual Studio, NUnit GUI/Console apps, ReSharper, TestDriven.Net, Gallio
  • 7.
    Unit test [TestFixture] public classCalculatorTests { [Test] public void Sum_ReturnsCorrectValue() { var math = new Calculator(); int result = math.Sum(1, 2); Assert.AreEqual(3, result); } }
  • 8.
    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 } }
  • 9.
    Що тестувати • Код,що містить логіку private DateTime _startDate; // doesn’t need to be tested public DateTime StartDate { get { return _startDate; } set { _startDate = value; } }
  • 10.
    Єдиний assert • Юніт-тестповинен тестувати щось одне • Назва тесту важлива [Test] public void Start_Test() { var survey = new Survey(); survey.Start(); Assert.AreEqual(SurveyState.InProgress, survey.State); Assert.IsTrue(survey.FinishDate > survey.StartDate); }
  • 11.
  • 12.
    DEMO [Test] public void Start_ChangesStateToInProgress() { var survey = new Survey(); survey.Start(); Assert.AreEqual(SurveyState.InProgress, survey.State); }
  • 13.
    Залежності • Survey залежить від EmailSender • Не хочемо відсилати справжні листи • Створюємо stub вручну • Створюємо stub автоматично • Все ще тестуємо стан! Assert.AreEqual(SurveyState.InProgress, survey.State);
  • 14.
    Interaction testing • Потреба тестувати взаємодії • Створюємо mock вручну • Створюємо mock автоматично • Один mock на тест • Тестуємо не стан, а взаємодію! mockEmailSender.Verify();
  • 15.
    Особливості тестів наповедінку • Реалізують діаграми послідовності (sequence diagram) • Дозволяють розробляти “згори вниз” • отримуючи API “нижчих” об’єктів “автоматично”
  • 16.
    Stubs + mocks •Один тест – один mock • Декілька stubs Fakes Stubs Mocks 0..* 0..1
  • 17.
  • 18.
    How unit testinghelps • Швидший цикл тестування коду • Коротший фідбек про можливі дефекти • Дефекти дешевші
  • 19.
    Плюси тестів • Кращий код • Стабільніша нова функціональність • Більше впевненості у змінах • Менше регресій • Коротші цикли релізів
  • 20.
  • 21.
    Види тестів • Юніт •Інтеграційні • Інші
  • 22.
    Юніт тести • Тестують один модуль • Виконуються виключно в пам’яті • Не вимагають конфігурації • Не вимагають DB, FS, AD, Net • Завжди – Повторювано проходять – Або повторювано не проходять – Тому що не залежать від змінних факторів
  • 23.
    Інтеграційні тести • Тестуютьмодулі разом • Можуть мати різну поведінку • В залежності від – Середовища (FS, DB, AD, OS, .config) – Порядку виконання – Кількості виконання – Багатопоточності – Повного місяця
  • 24.
    Інтеграційні тести --Ознаки • TearDown() • DateTime.Now • Thread • Environment.MachineName • Database.Save(…) • File.Open(…)
  • 25.
    Структура проекту • Чіткерозділення UT та IT
  • 26.
    Trustworthy • Юніт-тести –ДОВІРА – Проходять --> мабуть немає дефекту – Не проходять --> точно є дефект • Інтеграційні тести – (деколи) НЕДОВІРА – Проходять --> немає дефекту – Не проходять --> можливо дефект
  • 27.
  • 28.
    Якщо в кодіпомилка, тести повинні це показувати • Спосіб перевірки – внести помилку і перевірити, як тести про це сповіщають
  • 29.
    Логіка в юніт-тестах •Asserts in if/switch/for/while • Значно підвищується ймовірність появи дефекта в тесті • Погіршується readability & maintainability
  • 30.
    Дублювання логіки productionкоду • Приклад • Tests last • Тест не тестує • Expected hardcoded values
  • 31.
    Magic numbers • Приклад •Найпростіші можливі значення • Оголошення і перевірка в тесті
  • 32.
    Зміна тестів • Створення: – У більшості випадків • Видалення: – Коли тест більше не потрібний • Редагування: – Для maintainability/readability – Для швидкості – Коли тест повинен виконуватись по-іншому
  • 33.
    Тестувальник знаходить дефект •Пишемо новий тест • Дефект не повинен бути знайдений тестувальниками знову
  • 34.