SlideShare a Scribd company logo
Automated testing basics for
developers
Bohdan Pashkovskyi
Senior .NET Software Engineer at Perfectial
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Що таке тестування?
2 + 2 = ?
Ivano Frankivsk 2018
Тестування програмного забезпечення — процес перевірки на
відповідність між реальною та очікуваною поведінкою програми …
Навіщо тестувати програми?
Тестування не може довести відсутності дефектів, лише їх
наявність
Ivano Frankivsk 2018
В будь-якій програмі є дефекти
Яким буває тестування?
Ivano Frankivsk 2018
Нефункціональне
тестування
Тестування пов’язане зі змінамиФункціональне тестування
Модульне
Інтеграційне
Системне
Приймальне
Тестування
продуктивності
Відмовостійкості
Установки
Зручності
Регресійне
На дим
Санітарне
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Unit test (модульний тест)
Це код (зазвичай, метод), який викликає інший код (production) і
після цього перевіряє правильність деяких припущень
Ivano Frankivsk 2018
Unit тести
• Тестують один модуль
• Виконуються виключно в пам’яті
• Не вимагають конфігурації
• Не вимагають DB, FS, AD, Net
• Завжди
Повторювано проходять
Або повторювано не проходять
Тому що не залежать від змінних факторів
Ivano Frankivsk 2018
Інтеграційні тести
Тестують модулі разом
Можуть мати різну поведінку, в залежності від
• Середовища (FS, DB, AD, OS, .config)
• Порядку виконання
• Кількості виконання
• Багато поточності
• Повного місяця
Ivano Frankivsk 2018
Ознаки інтеграційних тестів
• TearDown()
• DateTime.Now
• Thread
• Environment.MachineName
• Database.Save(…)
• File.Open(…)
Ivano Frankivsk 2018
Приклад
модульного
тесту
Ivano Frankivsk 2018
[TestClass]
public class OrderTests
{
[TestMethod]
public void OrderApproval_ShouldChangeOrderStatusToApproved()
{
var order = new Order();
order.Approve();
Assert.AreEqual(OrderStatus.Approved, order.Status);
}
}
A A A
Ivano Frankivsk 2018
[TestClass]
public class OrderTests
{
[TestMethod]
public void OrderApproval_ShouldChangeOrderStatusToApproved()
{
// Arrange
var order = new Order();
// Act
order.Approve();
// Assert
Assert.AreEqual(OrderStatus.Approved, order.Status);
}
}
Unit tests frameworks
• Виконання тестів
• Інтеграція з IDE
• API для написання тестів
• Автоматизація
• Перегляд результатів
NUnit, MS Test, Xunit, MBUnit, DBUnit
Test runners:
Visual Studio, NUnit GUI/Console apps, ReSharper
Ivano Frankivsk 2018
Unit tests
frameworks
Ivano Frankivsk 2018
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Dependency
Ivano Frankivsk 2018
public class OrderManager
{
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
// dependency
var mailSender = new MailSender();
mailSender.Send("admin@example.com", "Order was approved");
}
}
Dependency injection
DI – це процес надання зовнішньої залежності програмному
компоненту. Є специфічною формою «інверсії керування»
(Inversion of Control, IoC)
Розрізняють дві основні форми DI (взагалі-то три )
- ін’єкція у конструктор (constructor injection)
- ін’єкція у властивість (setter/property injection)
Ivano Frankivsk 2018
DI крок 1
абстракція
Ivano Frankivsk 2018
public interface IMailSender
{
void Send(string address, string message);
}
public class MailSender : IMailSender
{
public void Send(string email, string message)
{ ... }
}
Constructor
injection
Ivano Frankivsk 2018
class OrderManager
{
private readonly IMailSender _mailSender;
public OrderManager(IMailSender mailSender)
{
_mailSender = mailSender;
}
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
_mailSender.Send("admin@saasap.net", "Order was approved");
}
}
Constructor
injection
Ivano Frankivsk 2018
var mailSender = new MailSender();
var orderManager = new OrderManager(mailSender);
orderManager.ApproveOrder(orderToApprove);
Setter
injection
Ivano Frankivsk 2018
class OrderManager
{
public IMailSender MailSender { get; set; }
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
MailSender.Send("admin@saasap.net", "Order was approved");
}
}
Setter
injection
Ivano Frankivsk 2018
class OrderManager
{
public IMailSender MailSender { get; set; }
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
MailSender.Send("admin@saasap.net", "Order was approved");
}
}
Setter
injection
Ivano Frankivsk 2018
var mailSender = new MailSender();
var orderManager = new OrderManager();
orderManager.MailSender = mailSender;
orderManager.ApproveOrder(orderToApprove);
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Inversion of Control
• Модулі вищого рівня не повинні залежати від модулів нижчого
рівня. Обидва типи модулів повинні залежати від абстракцій.
• Абстракції не повинні залежати від деталей реалізації. Деталі
реалізації повинні залежати від абстракцій.
Ivano Frankivsk 2018
IoC Containers
• Unity Application Block 2.0
• Spring.NET
• Structuremap
• CastleProject
• Seasar
• Winter.NET
• Ninject
Ivano Frankivsk 2018
IoC
Containers
Ivano Frankivsk 2018
public class IOCConfig
{
public static Container Container;
public static void Initialize()
{
Container = new Container(x =>
{
// constructor
x.For<IMailSender>().Use<MailSender>();
// setter
x.Policies.FillAllPropertiesOfType<IMailSender>().Use<MailSender>();
});
}
}
public class Test
{
public IMailSender MailSender = IOCConfig.Container.GetInstance<IMailSender>();
}
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Stubs (заглушка)
Стаби (заглушки) використовуються для того, щоб не
використовувати реальні залежності (файлову систему, БД,
поштові серери, тощо).
Це дозволяє тестувати тільки необхідний компонент
Стабів у тесті може бути багато.
Ivano Frankivsk 2018
Dependency
Ivano Frankivsk 2018
public class OrderManager
{
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
// dependency
var mailSender = new MailSender();
mailSender.Send("admin@example.com", "Order was approved");
}
}
DI крок 1
абстракція
Ivano Frankivsk 2018
public interface IMailSender
{
void Send(string address, string message);
}
public class MailSender : IMailSender
{
public void Send(string email, string message)
{ ... }
}
Stubs
Ivano Frankivsk 2018
public class StubMailSender : IMailSender
{
public void Send(string email, string message)
{
// do nothing
}
}
Stubs
Ivano Frankivsk 2018
[TestMethod]
public void OrderApproveMethod_ShouldChangeOrderStatusToApproved()
{
// Arrange
var order = new Order();
var orderManager = new OrderManager(new StubMailSender());
// Act
orderManager.ApproveOrder(order);
// Assert
Assert.AreEqual(OrderStatus.Approved, order.Status);
}
Isolation
frameworks
(Moq, RhinoMocks, etc)
Ivano Frankivsk 2018
[TestMethod]
public void OrderApproveMethod_ShouldChangeOrderStatusToApproved()
{
// Arrange
var order = new Order();
var stubMailSender = new Mock<IMailSender>();
var orderManager = new
OrderManager(stubMailSender.Object);
// Act
orderManager.ApproveOrder(order);
// Assert, все ще тестуємо стан
Assert.AreEqual(OrderStatus.Approved, order.Status);
}
Mocks
Mock використовуються для того, щоб протестувати взаємодію
залежностей.
Mock може бути лише один у тесті.
Один Assert = Один Verify
Ivano Frankivsk 2018
Mocks
Ivano Frankivsk 2018
[TestMethod]
public void OrderApproveMethod_ShouldChangeOrderStatusToApproved()
{
// Arrange
var order = new Order();
var mockMailSender = new Mock<IMailSender>();
mockMailSender.Setup(ms => ms.Send(
"admin@example.com",
It.IsAny<string>()))
.Verifiable();
var orderManager = new OrderManager(mockMailSender.Object);
// Act
orderManager.ApproveOrder(order);
// Assert
mockMailSender.Verify();
}
Stubs +
mocks
(Один тест – один mock, але декілька stubs)
Ivano Frankivsk 2018
Fakes
Stubs 0..* Mocks 0..1
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
Що
тестувати
Ivano Frankivsk 2018
public class Order
{
private string _title;
public string Title
{
get { return _title; }
set { _title = value; }
}
}
Переваги модульних тестів
• Швидший цикл тестування коду
• Коротший фідбек про можливі дефекти
• Дефекти дешевші
• Кращий код
• Стабільніша нова функціональність
• Більше впевненості у змінах
• Менше регресій
• Коротші цикли релізів
Ivano Frankivsk 2018
Якості модульних тестів
• Readable
• Maintainable
• Trustworthy
Ivano Frankivsk 2018
Readable
• Що відбувається в тесті
• Який код тестується
• Які передумови
• Які припущення перевіряються
• Що тестує тест
• Простий код тесту
Ivano Frankivsk 2018
Maintainable
• Тести легко реагують на зміни
• Не вимагають конфігурації
• Не залежать від інших тестів
• Простий код тесту
Ivano Frankivsk 2018
Trustworthy
• Релевантні до помилок
• Стабільно (не) проходять
• Немає конфліктуючих тестів
• Справді тестують
Ivano Frankivsk 2018
Agenda
Ivano Frankivsk 2018
Що таке тестування і яким воно буває?
Unit tests vs Integration tests
Dependency Injection
Inversion of Control
Якості хороших unit тестів
Fakes (stubs + mocks)
TDD + BDD
TDD
Ivano Frankivsk 2018
BDD
Ivano Frankivsk 2018
Speckflow
(Cucumber for .NET)
Ivano Frankivsk 2018
Speckflow
Feature example
Ivano Frankivsk 2018
Feature: Calculator_Add
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Background:
Given I have a calculator
Scenario: Add two numbers
Given I enter 50 into the calculator
And I press plus
And I enter 70 into the calculator
When I press enter
Then the result should be 120 be displayed
Speckflow
Bindings
Ivano Frankivsk 2018[Binding]
public class Calculator_SharedSteps
{
[Given(@"I have a calculator")]
public void GivenIHaveACalculator()
{
ScenarioContext.Current.Set<Calculator>(new Calculator());
}
[Given(@"I enter (.*) into the calculator")]
public void GivenIEnterIntoTheCalculator(int p0)
{
ScenarioContext.Current.Get<Calculator>().Number(p0);
}
[When(@"I press enter")]
public void WhenIPressEnter()
{
ScenarioContext.Current.Get<Calculator>().Enter();
}
[Then(@"the result should be (.*) be displayed")]
public void ThenTheResultShouldBeBeDisplayed(int p0)
{
Assert.AreEqual(Convert.ToString(p0),
ScenarioContext.Current.Get<Calculator>().Display);
}
}
Speckflow
Web example
Ivano Frankivsk 2018
Feature: Login page should give ability to Login or Register for
Background:
Given I am not logged in
And I am on "/account/login" page
Scenario: When I enter empty pass in Login form, I should see
error message
When I have filled out the form as follows
| Id | Value |
| Login_Password | |
And I press input type "submit" with value „Login"
Then I should see error „Required" for Login_Password
Scenario: If I am logged In a am redirected to account details
When I log in as user
And I go to "/account/login" page
Then I should be on page "/account/details"
Code
coverage
Ivano Frankivsk 2018
Ivano Frankivsk 2018

More Related Content

Similar to CoreCamp "Automated testing basics for developers" (20)

PPTX
Code driven testing (UA)
Oleksandr Pavlyshak
 
PPTX
Як покращити Python web UI тести
RomanPobotin1
 
PPTX
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Exoft LLC
 
PDF
Tdd, ти де?
Roman Mazur
 
PDF
Lviv PMDay: Дмитро Лозовицький Складові поняття “якості”, якість процесу робо...
Lviv Startup Club
 
PPTX
13 testing
eleksdev
 
PDF
Тестування при розробці програмного забезпечення. Unit Tests.
Elantix
 
PPT
V24 com to_net
Ringonoki
 
PPTX
Automation as a Way to Do Routine Work Quickly and Effortlessly
GlobalLogic Ukraine
 
PDF
Упр. ІТпроектами 6 лекція Добривода Наталя, СН-21
Oleg Nazarevych
 
PPTX
Automated testing
Bohdan Pashkovskyi
 
PDF
Php unit. Y. Muzychushun
HRdepartment
 
PPT
реалізація проекту
Oleg Nazarevych
 
PDF
"Unit testing in AngularJS" Виктор Зозуляк
Fwdays
 
PPT
Caliburn Micro Overview
Kiev ALT.NET
 
PDF
РІНА УЖЕВКО «Вплив архітектури на стратегію тестування»
QADay
 
PPTX
ASP.Net MVC
Victor Matyushevskyy
 
PPTX
природна і економна дорожня карта для переходу команди розробки на тест центр...
Andrii Podanenko
 
PDF
ОКСАНА ТРОЯН «Щоб рейки зійшлись в одній точці: від кількості до якості. Як к...
QADay
 
PPTX
Якість продукту при створенні ПЗ. SDLC (Software development lifecycle). Роль...
Elantix
 
Code driven testing (UA)
Oleksandr Pavlyshak
 
Як покращити Python web UI тести
RomanPobotin1
 
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Exoft LLC
 
Tdd, ти де?
Roman Mazur
 
Lviv PMDay: Дмитро Лозовицький Складові поняття “якості”, якість процесу робо...
Lviv Startup Club
 
13 testing
eleksdev
 
Тестування при розробці програмного забезпечення. Unit Tests.
Elantix
 
V24 com to_net
Ringonoki
 
Automation as a Way to Do Routine Work Quickly and Effortlessly
GlobalLogic Ukraine
 
Упр. ІТпроектами 6 лекція Добривода Наталя, СН-21
Oleg Nazarevych
 
Automated testing
Bohdan Pashkovskyi
 
Php unit. Y. Muzychushun
HRdepartment
 
реалізація проекту
Oleg Nazarevych
 
"Unit testing in AngularJS" Виктор Зозуляк
Fwdays
 
Caliburn Micro Overview
Kiev ALT.NET
 
РІНА УЖЕВКО «Вплив архітектури на стратегію тестування»
QADay
 
природна і економна дорожня карта для переходу команди розробки на тест центр...
Andrii Podanenko
 
ОКСАНА ТРОЯН «Щоб рейки зійшлись в одній точці: від кількості до якості. Як к...
QADay
 
Якість продукту при створенні ПЗ. SDLC (Software development lifecycle). Роль...
Elantix
 

More from Bohdan Pashkovskyi (9)

PDF
Деякі аспекти встановлення дорожніх знаків
Bohdan Pashkovskyi
 
PPTX
Telegram bots
Bohdan Pashkovskyi
 
PPTX
CQRS and Event Sourcing
Bohdan Pashkovskyi
 
PPTX
C# Lesson 3
Bohdan Pashkovskyi
 
PPTX
C# Lesson 1
Bohdan Pashkovskyi
 
PPTX
IF .NET User Group
Bohdan Pashkovskyi
 
PPTX
Asynchronous programming in C#
Bohdan Pashkovskyi
 
PPTX
ASP .NET MVC - best practices
Bohdan Pashkovskyi
 
PPTX
.Net Core
Bohdan Pashkovskyi
 
Деякі аспекти встановлення дорожніх знаків
Bohdan Pashkovskyi
 
Telegram bots
Bohdan Pashkovskyi
 
CQRS and Event Sourcing
Bohdan Pashkovskyi
 
C# Lesson 3
Bohdan Pashkovskyi
 
C# Lesson 1
Bohdan Pashkovskyi
 
IF .NET User Group
Bohdan Pashkovskyi
 
Asynchronous programming in C#
Bohdan Pashkovskyi
 
ASP .NET MVC - best practices
Bohdan Pashkovskyi
 
Ad

CoreCamp "Automated testing basics for developers"

  • 1. Automated testing basics for developers Bohdan Pashkovskyi Senior .NET Software Engineer at Perfectial
  • 2. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 3. Що таке тестування? 2 + 2 = ? Ivano Frankivsk 2018 Тестування програмного забезпечення — процес перевірки на відповідність між реальною та очікуваною поведінкою програми …
  • 4. Навіщо тестувати програми? Тестування не може довести відсутності дефектів, лише їх наявність Ivano Frankivsk 2018 В будь-якій програмі є дефекти
  • 5. Яким буває тестування? Ivano Frankivsk 2018 Нефункціональне тестування Тестування пов’язане зі змінамиФункціональне тестування Модульне Інтеграційне Системне Приймальне Тестування продуктивності Відмовостійкості Установки Зручності Регресійне На дим Санітарне
  • 6. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 7. Unit test (модульний тест) Це код (зазвичай, метод), який викликає інший код (production) і після цього перевіряє правильність деяких припущень Ivano Frankivsk 2018
  • 8. Unit тести • Тестують один модуль • Виконуються виключно в пам’яті • Не вимагають конфігурації • Не вимагають DB, FS, AD, Net • Завжди Повторювано проходять Або повторювано не проходять Тому що не залежать від змінних факторів Ivano Frankivsk 2018
  • 9. Інтеграційні тести Тестують модулі разом Можуть мати різну поведінку, в залежності від • Середовища (FS, DB, AD, OS, .config) • Порядку виконання • Кількості виконання • Багато поточності • Повного місяця Ivano Frankivsk 2018
  • 10. Ознаки інтеграційних тестів • TearDown() • DateTime.Now • Thread • Environment.MachineName • Database.Save(…) • File.Open(…) Ivano Frankivsk 2018
  • 11. Приклад модульного тесту Ivano Frankivsk 2018 [TestClass] public class OrderTests { [TestMethod] public void OrderApproval_ShouldChangeOrderStatusToApproved() { var order = new Order(); order.Approve(); Assert.AreEqual(OrderStatus.Approved, order.Status); } }
  • 12. A A A Ivano Frankivsk 2018 [TestClass] public class OrderTests { [TestMethod] public void OrderApproval_ShouldChangeOrderStatusToApproved() { // Arrange var order = new Order(); // Act order.Approve(); // Assert Assert.AreEqual(OrderStatus.Approved, order.Status); } }
  • 13. Unit tests frameworks • Виконання тестів • Інтеграція з IDE • API для написання тестів • Автоматизація • Перегляд результатів NUnit, MS Test, Xunit, MBUnit, DBUnit Test runners: Visual Studio, NUnit GUI/Console apps, ReSharper Ivano Frankivsk 2018
  • 15. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 16. Dependency Ivano Frankivsk 2018 public class OrderManager { public void ApproveOrder(Order orderToApprove) { orderToApprove.Approve(); // dependency var mailSender = new MailSender(); mailSender.Send("[email protected]", "Order was approved"); } }
  • 17. Dependency injection DI – це процес надання зовнішньої залежності програмному компоненту. Є специфічною формою «інверсії керування» (Inversion of Control, IoC) Розрізняють дві основні форми DI (взагалі-то три ) - ін’єкція у конструктор (constructor injection) - ін’єкція у властивість (setter/property injection) Ivano Frankivsk 2018
  • 18. DI крок 1 абстракція Ivano Frankivsk 2018 public interface IMailSender { void Send(string address, string message); } public class MailSender : IMailSender { public void Send(string email, string message) { ... } }
  • 19. Constructor injection Ivano Frankivsk 2018 class OrderManager { private readonly IMailSender _mailSender; public OrderManager(IMailSender mailSender) { _mailSender = mailSender; } public void ApproveOrder(Order orderToApprove) { orderToApprove.Approve(); _mailSender.Send("[email protected]", "Order was approved"); } }
  • 20. Constructor injection Ivano Frankivsk 2018 var mailSender = new MailSender(); var orderManager = new OrderManager(mailSender); orderManager.ApproveOrder(orderToApprove);
  • 21. Setter injection Ivano Frankivsk 2018 class OrderManager { public IMailSender MailSender { get; set; } public void ApproveOrder(Order orderToApprove) { orderToApprove.Approve(); MailSender.Send("[email protected]", "Order was approved"); } }
  • 22. Setter injection Ivano Frankivsk 2018 class OrderManager { public IMailSender MailSender { get; set; } public void ApproveOrder(Order orderToApprove) { orderToApprove.Approve(); MailSender.Send("[email protected]", "Order was approved"); } }
  • 23. Setter injection Ivano Frankivsk 2018 var mailSender = new MailSender(); var orderManager = new OrderManager(); orderManager.MailSender = mailSender; orderManager.ApproveOrder(orderToApprove);
  • 24. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 25. Inversion of Control • Модулі вищого рівня не повинні залежати від модулів нижчого рівня. Обидва типи модулів повинні залежати від абстракцій. • Абстракції не повинні залежати від деталей реалізації. Деталі реалізації повинні залежати від абстракцій. Ivano Frankivsk 2018
  • 26. IoC Containers • Unity Application Block 2.0 • Spring.NET • Structuremap • CastleProject • Seasar • Winter.NET • Ninject Ivano Frankivsk 2018
  • 27. IoC Containers Ivano Frankivsk 2018 public class IOCConfig { public static Container Container; public static void Initialize() { Container = new Container(x => { // constructor x.For<IMailSender>().Use<MailSender>(); // setter x.Policies.FillAllPropertiesOfType<IMailSender>().Use<MailSender>(); }); } } public class Test { public IMailSender MailSender = IOCConfig.Container.GetInstance<IMailSender>(); }
  • 28. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 29. Stubs (заглушка) Стаби (заглушки) використовуються для того, щоб не використовувати реальні залежності (файлову систему, БД, поштові серери, тощо). Це дозволяє тестувати тільки необхідний компонент Стабів у тесті може бути багато. Ivano Frankivsk 2018
  • 30. Dependency Ivano Frankivsk 2018 public class OrderManager { public void ApproveOrder(Order orderToApprove) { orderToApprove.Approve(); // dependency var mailSender = new MailSender(); mailSender.Send("[email protected]", "Order was approved"); } }
  • 31. DI крок 1 абстракція Ivano Frankivsk 2018 public interface IMailSender { void Send(string address, string message); } public class MailSender : IMailSender { public void Send(string email, string message) { ... } }
  • 32. Stubs Ivano Frankivsk 2018 public class StubMailSender : IMailSender { public void Send(string email, string message) { // do nothing } }
  • 33. Stubs Ivano Frankivsk 2018 [TestMethod] public void OrderApproveMethod_ShouldChangeOrderStatusToApproved() { // Arrange var order = new Order(); var orderManager = new OrderManager(new StubMailSender()); // Act orderManager.ApproveOrder(order); // Assert Assert.AreEqual(OrderStatus.Approved, order.Status); }
  • 34. Isolation frameworks (Moq, RhinoMocks, etc) Ivano Frankivsk 2018 [TestMethod] public void OrderApproveMethod_ShouldChangeOrderStatusToApproved() { // Arrange var order = new Order(); var stubMailSender = new Mock<IMailSender>(); var orderManager = new OrderManager(stubMailSender.Object); // Act orderManager.ApproveOrder(order); // Assert, все ще тестуємо стан Assert.AreEqual(OrderStatus.Approved, order.Status); }
  • 35. Mocks Mock використовуються для того, щоб протестувати взаємодію залежностей. Mock може бути лише один у тесті. Один Assert = Один Verify Ivano Frankivsk 2018
  • 36. Mocks Ivano Frankivsk 2018 [TestMethod] public void OrderApproveMethod_ShouldChangeOrderStatusToApproved() { // Arrange var order = new Order(); var mockMailSender = new Mock<IMailSender>(); mockMailSender.Setup(ms => ms.Send( "[email protected]", It.IsAny<string>())) .Verifiable(); var orderManager = new OrderManager(mockMailSender.Object); // Act orderManager.ApproveOrder(order); // Assert mockMailSender.Verify(); }
  • 37. Stubs + mocks (Один тест – один mock, але декілька stubs) Ivano Frankivsk 2018 Fakes Stubs 0..* Mocks 0..1
  • 38. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 39. Що тестувати Ivano Frankivsk 2018 public class Order { private string _title; public string Title { get { return _title; } set { _title = value; } } }
  • 40. Переваги модульних тестів • Швидший цикл тестування коду • Коротший фідбек про можливі дефекти • Дефекти дешевші • Кращий код • Стабільніша нова функціональність • Більше впевненості у змінах • Менше регресій • Коротші цикли релізів Ivano Frankivsk 2018
  • 41. Якості модульних тестів • Readable • Maintainable • Trustworthy Ivano Frankivsk 2018
  • 42. Readable • Що відбувається в тесті • Який код тестується • Які передумови • Які припущення перевіряються • Що тестує тест • Простий код тесту Ivano Frankivsk 2018
  • 43. Maintainable • Тести легко реагують на зміни • Не вимагають конфігурації • Не залежать від інших тестів • Простий код тесту Ivano Frankivsk 2018
  • 44. Trustworthy • Релевантні до помилок • Стабільно (не) проходять • Немає конфліктуючих тестів • Справді тестують Ivano Frankivsk 2018
  • 45. Agenda Ivano Frankivsk 2018 Що таке тестування і яким воно буває? Unit tests vs Integration tests Dependency Injection Inversion of Control Якості хороших unit тестів Fakes (stubs + mocks) TDD + BDD
  • 49. Speckflow Feature example Ivano Frankivsk 2018 Feature: Calculator_Add In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Background: Given I have a calculator Scenario: Add two numbers Given I enter 50 into the calculator And I press plus And I enter 70 into the calculator When I press enter Then the result should be 120 be displayed
  • 50. Speckflow Bindings Ivano Frankivsk 2018[Binding] public class Calculator_SharedSteps { [Given(@"I have a calculator")] public void GivenIHaveACalculator() { ScenarioContext.Current.Set<Calculator>(new Calculator()); } [Given(@"I enter (.*) into the calculator")] public void GivenIEnterIntoTheCalculator(int p0) { ScenarioContext.Current.Get<Calculator>().Number(p0); } [When(@"I press enter")] public void WhenIPressEnter() { ScenarioContext.Current.Get<Calculator>().Enter(); } [Then(@"the result should be (.*) be displayed")] public void ThenTheResultShouldBeBeDisplayed(int p0) { Assert.AreEqual(Convert.ToString(p0), ScenarioContext.Current.Get<Calculator>().Display); } }
  • 51. Speckflow Web example Ivano Frankivsk 2018 Feature: Login page should give ability to Login or Register for Background: Given I am not logged in And I am on "/account/login" page Scenario: When I enter empty pass in Login form, I should see error message When I have filled out the form as follows | Id | Value | | Login_Password | | And I press input type "submit" with value „Login" Then I should see error „Required" for Login_Password Scenario: If I am logged In a am redirected to account details When I log in as user And I go to "/account/login" page Then I should be on page "/account/details"