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

PPTX
QA Fes 2016. Яна Кокряшкіна. Визначення автоматизованого тестового покриття д...
ODP
Процес забезпечення якості програмних продуктів
PPTX
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
PPTX
Automated testing
PPTX
Code driven testing (UA)
PPTX
Code driven testing -- oleksandr pavlyshak
PPTX
Automated testing
PDF
Тестування з допомогою PHPUnit
QA Fes 2016. Яна Кокряшкіна. Визначення автоматизованого тестового покриття д...
Процес забезпечення якості програмних продуктів
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Automated testing
Code driven testing (UA)
Code driven testing -- oleksandr pavlyshak
Automated testing
Тестування з допомогою PHPUnit

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

PPTX
PPTX
13 testing
PPTX
ОЛЕГ ЗАРЕВИЧ «How did we improve delivery using tests» Lviv QA Day 2019
ODP
Phpunit модульне тестування
PDF
Testing in Ruby
PPTX
природна і економна дорожня карта для переходу команди розробки на тест центр...
PPTX
cpp-2013 #16 Automated testing
PDF
Тестування при розробці програмного забезпечення. Unit Tests.
PPTX
Design patterns part 1
PDF
РІНА УЖЕВКО «Вплив архітектури на стратегію тестування»
PPTX
Хто такий тестувальник? (Who is tester?)
PPTX
Марина Мінак-Супруненко Agile очима ISTQB
PDF
"Unit testing in AngularJS" Виктор Зозуляк
13 testing
ОЛЕГ ЗАРЕВИЧ «How did we improve delivery using tests» Lviv QA Day 2019
Phpunit модульне тестування
Testing in Ruby
природна і економна дорожня карта для переходу команди розробки на тест центр...
cpp-2013 #16 Automated testing
Тестування при розробці програмного забезпечення. Unit Tests.
Design patterns part 1
РІНА УЖЕВКО «Вплив архітектури на стратегію тестування»
Хто такий тестувальник? (Who is tester?)
Марина Мінак-Супруненко Agile очима ISTQB
"Unit testing in AngularJS" Виктор Зозуляк
Ad

More from Bohdan Pashkovskyi (9)

PDF
Деякі аспекти встановлення дорожніх знаків
PPTX
Telegram bots
PPTX
CQRS and Event Sourcing
PPTX
C# Lesson 3
PPTX
C# Lesson 1
PPTX
IF .NET User Group
PPTX
Asynchronous programming in C#
PPTX
ASP .NET MVC - best practices
PPTX
Деякі аспекти встановлення дорожніх знаків
Telegram bots
CQRS and Event Sourcing
C# Lesson 3
C# Lesson 1
IF .NET User Group
Asynchronous programming in C#
ASP .NET MVC - best practices
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("admin@example.com", "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("admin@saasap.net", "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("admin@saasap.net", "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("admin@saasap.net", "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("admin@example.com", "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( "admin@example.com", 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"