2. Що таке тестування?
Тестування програмного забезпечення — процес перевірки на відповідність між реальною
та очікуваною поведінкою програми.
Починається разом із розробкою
• Запускаємо і дивимось чи працює
• Створюємо допоміжні засоби
• Консольні програми
• Допоміжний UI
SAAS APPS
3. Навіщо тестувати програми?
◦ Тестування не підвищує якість ПЗ, а сприяє розпізнаванню неправильної поведінки, завдяки чому
розробники можуть знайти помилки і виправити їх;
◦ Тестування не може довести відсутності дефектів, лише їх наявність
◦ В будь-якій програмі є дефекти
SAAS APPS
4. Яким буває тестування?
SAAS APPS
Нефункціональне тестування Тестування пов’язане зі змінамиФункціональне тестування
Модульне
Інтеграційне
Системне
Приймальне
Тестування
продуктивності
Відказостійкості
Установки
Зручності
Регресійне
На дим
Санітарне
5. Функціональне тестування
Модульне тестування (англ. Unit testing) — це метод тестування програмного забезпечення, який полягає в окремому тестуванні
кожного модуля коду програми. Модулем називають найменшу частину програми, яку може бути протестованою (об’єкт, клас,
функція).
Інтеграційне тестування (англ. Integration testing) — це фаза тестування програмного забезпечення, під час якої окремі модулі
програми комбінуються та тестуються разом, у взаємодії.
Системне тестування (англ. System testing) тестує інтегровану систему для перевірки відповідності всім вимогам. Виявляє наступні
дефекти:
• невірне використання ресурсів системи,
• непередбачувані комбінації даних користувальницького рівня,
• несумісність із оточенням,
• непередбачувані сценарії використання,
• відсутня або невірна функціональність,
• незручність у застосуванні тощо.
Приймальне тестування (англ. Acceptance testing) – формальний процес тестування, який перевіряє відповідність системи вимогам
і проводиться з метою визначення чи задовільняє система приймальним критеріям замовника.
SAAS APPS
6. Модульне (unit) тестування
Unit test, визначення:
◦ це код (зазвичай, метод), який викликає інший код (production) і після цього перевіряє
правильність деяких припущень
SAAS APPS
7. Модульні тести
Тестують один модуль
Виконуються виключно в пам’яті
Не вимагають конфігурації
Не вимагають DB, FS, AD, Net
Завжди
◦ Повторювано проходять
◦ Або повторювано не проходять
◦ Тому що не залежать від змінних факторів
SAAS APPS
8. Інтеграційні тести
Тестують модулі разом
Можуть мати різну поведінку
В залежності від
◦ Середовища (FS, DB, AD, OS, .config)
◦ Порядку виконання
◦ Кількості виконання
◦ Багатопоточності
◦ Повного місяця
SAAS APPS
10. Unit test
framework
•Виконання тестів
• Одного, декількох, всіх
• Інтеграція з IDE
• API для написання тестів
• Автоматизація
• Перегляд результатів
NUnit, MS Test, Xunit,
MBUnit, DBUnit
Test runners:
Visual Studio, NUnit
GUI/Console apps, ReSharper,
SAAS APPS
12. A A A
Arrange/Act/Assert
SAAS APPS
[TestClass]
public class OrderTests
{
[TestMethod]
public void
OrderApproval_ShouldChangeOrderStatusToApproved()
{
var order = new Order(); // Arrange
order.Approve(); // Act
Assert.AreEqual(OrderStatus.Approved,
order.Status); // Assert
}
}
13. Що тестувати?
Код, що містить логіку
public class Order
{
private string _title;
public string Title
{
get { return _title; }
set { _title = value; }
}
SAAS APPS
14. Єдиний Assert
[TestClass]
public class OrderTests
{
[TestMethod]
public void OrderApproval
_ShouldChangeOrderStatusToApproved
_AndOrderApproverShouldntBeNull()
{
var order = new Order();
order.Approve();
Assert.AreEqual(OrderStatus.Approved,
order.Status);
Assert.IsNotNull(order.OrderApprover);
}
}
SAAS APPS
15. Залежності
class OrderManager
{
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
var mailSender = new MailSender();
mailSender.Send("admin@saasap.net", "Order was
approved");
}
}
SAAS APPS
16. Dependency injection
DI – це процес надання зовнішньої залежності програмному компоненту. Є специфічною
формою «інверсії керування» (Inversion of Control, IoC)
Розрізняють дві основні форми DI (взагалі-то три )
- ін’єкція у конструктор (constructor injection)
- ін’єкція у властивість (setter/property injection)
SAAS APPS
17. DI (крок 1 –
абстрагування)
public interface IMailSender
{
void Send(string address, string message);
}
public class MailSender : IMailSender
{
public void Send(string email, string message)
{ ... }
}
SAAS APPS
18. Constructor
injection
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");
}
}
declaration
SAAS APPS
19. Constructor
injection var mailSender = new MailSender();
var orderManager = new OrderManager(mailSender);
orderManager.ApproveOrder(orderToApprove);
usage
SAAS APPS
20. Setter injection
class OrderManager
{
public IMailSender MailSender { get; set; }
public void ApproveOrder(Order orderToApprove)
{
orderToApprove.Approve();
MailSender.Send("admin@saasap.net", "Order was
approved");
}
}
declaration
SAAS APPS
21. Setter injection var mailSender = new MailSender();
var orderManager = new OrderManager();
orderManager.MailSender = mailSender;
orderManager.ApproveOrder(orderToApprove);
usage
SAAS APPS
22. IoC containers
Structuremap
public class IOCConfig
{
public static Container Container;
public static void Initialize()
{
Container = new Container(x =>
{
x.For<IMailSender>().Use<MailSender>(); // constructor
x.Policies.FillAllPropertiesOfType<IMailSender>().Use<MailSender>();
// setter
});
}
}
public class Test
{
public IMailSender MailSender = IOCConfig.Container.GetInstance<IMailSender>();
}
Unity Application Block 2.0
Spring.NET
Structuremap
CastleProject
Seasar
Winter.NET
Ninject
SAAS APPS
23. Stubs
public class StubMailSender : IMailSender
{
public void Send(string email, string message)
{
// do nothing
}
}
[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);
}
Стаби (заглушки) використовуються
для того, щоб не використовувати
реальні залежності (файлову
систему, БД, поштові серери, тощо).
Це дозволяє тестувати тільки
необхідний компонент
Стабів у тесті може бути багато.
SAAS APPS
24. Isolation
frameworks
Stubs with Moq
[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);
}
Moq, RhinoMocks, etc
SAAS APPS
25. Mocks
[TestMethod]
public void OrderApproveMethod_ShouldChangeOrderStatusToApproved()
{
// Arrange
var order = new Order();
var mockMailSender = new Mock<IMailSender>();
mockMailSender.Setup(ms => ms.Send(
"admin@saasap.net",
It.IsAny<string>()))
.Verifiable();
var orderManager = new OrderManager(mockMailSender.Object);
// Act
orderManager.ApproveOrder(order);
// Assert
mockMailSender.Verify();
}
Mock використовуються для того,
щоб протестувати взаємодію
залежностей.
Мок може бути лише один у тесті.
Один Assert = Один Verify
SAAS APPS
26. Stubs + mocks
Один тест – один mock, але декілька stubs
SAAS APPS
Fakes
Stubs
0..*
Mocks
0..1
27. Переваги модульних тестів
• Швидший цикл тестування коду
• Коротший фідбек про можливі дефекти
• Дефекти дешевші
• Кращий код
• Стабільніша нова функціональність
• Більше впевненості у змінах
• Менше регресій
• Коротші цикли релізів
SAAS APPS
29. Readable
Легко зрозуміти:
• Що відбувається в тесті
• Який код тестується
• Які передумови
• Які припущення перевіряються
• Що тестує тест
• Простий код тесту
SAAS APPS
30. Trustworthy
• Релевантні до помилок
• Стабільно (не) проходять
• Немає конфліктуючих тестів
• Справді тестують
SAAS APPS
31. Maintainable
• Тести легко реагують на зміни
• Не вимагають конфігурації
• Не залежать від інших тестів
• Простий код тесту
SAAS APPS
35. Speckflow
Feature example
SAAS APPS
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
36. Speckflow
Bindings
SAAS APPS
[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);
}
}
37. Specflow
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"
Web example
SAAS APPS