SlideShare a Scribd company logo
Тестирование Web API
Особенности моего проекта
— Большая зависимость от БД
— Зависимость от внешних сервисов
• Push сообщения
• Email
• Сокращение ссылок
• Платежи
Webapi
Внешние
сервисыБД Внутренние
сервисы
Боль тестирования
— Тестирование контроллеров
• Много мокать
• Сложная поддержка
• Не тестируются запросы к БД
— Интеграционные тесты
• Малое покрытие
• Очень трудно тестировать сложные сценарии
— Ручное тестирование
• Долго
• Никто не делает регресс
Доклад про TestServer — озарение!
— Выглядит просто
— Решил попробовать
— Сделал предположения
• можно мочить
• можно дебажить в том же процессе (в одной студии)
Внедрение TestServer
— Готовая реализация под .Net Core, а у меня классический .Net
— nUnit
— Внедрял параллельно разработке
Предметная область демо-проекта
— Есть группы
— У групп есть пользователи
— У пользователей есть роли: владелец, юзер и модератор
— Владелец может назначать модераторов
— Владелец и модератор могут публиковать заметки
Структура тестов
Test API client Requester API server
[OneTimeSetUp]
public void OneTimeSetUp()
{
ApiServer = new ApiServer();
var requester = ApiServer.GetRequester();
ApiClient = new ApiClient(requester);
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
ApiServer.Dispose();
}
[SetUp]
public void Setup()
{
ApiServer.Reset();
}
Test API client Requester API serverTest
— Администратор создаёт группу
— Пользователь вступает в группу
— Администратор назначает пользователя модератором
— Пользователь может создавать заметки
Test API client Requester API serverTest
Test API client Requester API serverTest
var adminToken = await ApiClient.Account.GetToken("123", "456");
var userToken = await ApiClient.Account.GetToken("aaa", "bbb");
var groupOwner = await ApiClient.Group.CreateGroup(adminToken, new CreateGroupDto
{
Name = "Тестовая группа " + DateTime.UtcNow.Ticks
});
GroupMember userMember = await ApiClient.Group.Join(userToken, groupOwner.Group.Id);
await ApiClient.Group.SetModerator(adminToken, groupOwner.Group.Id, userMember.Id);
var note = await ApiClient.Group.AddNote(
userToken, groupOwner.Group.Id, "Заметка от модератора");
Assert.That(note, Is.Not.Null);
Assert.That(note.Text, Is.EqualTo("Заметка от модератора"));
public class GroupApiClient
{
private readonly IHttpRequester _requester;
public GroupApiClient(IHttpRequester requester)
{
_requester = requester;
}
public async Task<GroupMemberDto[]> GetGroups(string token)
{
return await _requester.GetAsync<GroupMemberDto[]>("/api/group", token);
}
public async Task<GroupMemberDto> CreateGroup(string token, CreateGroupDto dto)
{
return await _requester
.PostAsync<CreateGroupDto, GroupMemberDto>("/api/group", token, dto);
}
Test API client Requester API serverAPI client
public HttpClient CreateClient(string token = null)
{
var client = new HttpClient(_handler) {BaseAddress = _baseAddress};
if (token != null)
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
return client;
}
public async Task<TResult> GetAsync<TResult>(string url, string token)
{
using (var client = CreateClient(token))
{
var response = await client.GetAsync(url);
await CheckStatusCode(response);
return await Deserialize<TResult>(response);
}
}
Test API client Requester API serverRequester
public class ApiServer : IDisposable
{
public TestServer TestServer { get; }
private TestStartup Startup { get; }
public ApiServer()
{
Startup = new TestStartup();
TestServer = TestServer.Create(app =>
{
Startup.Configuration(app);
});
}
public IHttpRequester GetRequester()
{
return new HttpRequester(TestServer.Handler, TestServer.BaseAddress);
}
public void Reset()
{
//Логика сброса моков перед каждым тестом
}
Test API client Requester API serverAPI server
public class TestStartup : Startup
{
protected override WindsorContainer CreateWindsorContainer()
{
var container = base.CreateWindsorContainer();
return container;
}
protected override IncludeErrorDetailPolicy GetErrorDetailPolicy()
=> IncludeErrorDetailPolicy.Always;
}
Test API client Requester API serverAPI server
Профит
— Тесты стали похожи на реальные пользовательские сценарии
— Отладка в одной студии
— Сокращение цикла отладки
— Внешние зависимости перестали мешать тестировать
— Уверенность в работоспособности системы увеличилась
Дальнейшее развитие
— Единожды создавать тест сервер в памяти
— Настроить запуск на TeamCity
— Мокать под конкретный тест
Спасибо за внимание!
Email: rusakov@byndyusoft.com
Vk: https://vk.com/id512458
GitHub: https://github.com/Mblkolo
Telegram: https://t.me/Mblkolo

More Related Content

What's hot

C# Desktop. Занятие 15.
C# Desktop. Занятие 15.C# Desktop. Занятие 15.
C# Desktop. Занятие 15.
Igor Shkulipa
 
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Yulia Tsisyk
 
Пользователь точно оценит! Повышение производительности мобильных приложений ...
Пользователь точно оценит! Повышение производительности мобильных приложений ...Пользователь точно оценит! Повышение производительности мобильных приложений ...
Пользователь точно оценит! Повышение производительности мобильных приложений ...
Ontico
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Noveo
 
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
Ontico
 
Продвинутое использование Celery — Александр Кошелев
Продвинутое использование Celery — Александр КошелевПродвинутое использование Celery — Александр Кошелев
Продвинутое использование Celery — Александр Кошелев
Yandex
 
Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0
matroskin1980
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Andrey Rebrov
 
Опыт разработки и тестирования RESTful JSON сервиса
Опыт разработки и тестирования RESTful JSON сервисаОпыт разработки и тестирования RESTful JSON сервиса
Опыт разработки и тестирования RESTful JSON сервиса
Ilya Chesnokov
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Noveo
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST API
Pavel Asanov
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + Retrofit
Dev2Dev
 
Реактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложенияРеактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложения
Matvey Malkov
 
Илья Ефимов «IoC/DI на примере Autofac»
Илья Ефимов «IoC/DI на примере Autofac»Илья Ефимов «IoC/DI на примере Autofac»
Илья Ефимов «IoC/DI на примере Autofac»
Yulia Tsisyk
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на Swift
RAMBLER&Co
 
Нейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
Нейронечёткая классификация слабо формализуемых данных | Тимур ГильмуллинНейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
Нейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
Positive Hack Days
 
Тестирование производительности систем мониторинга на платформе Microsoft SCO...
Тестирование производительности систем мониторинга на платформе Microsoft SCO...Тестирование производительности систем мониторинга на платформе Microsoft SCO...
Тестирование производительности систем мониторинга на платформе Microsoft SCO...
SQALab
 
WordPress REST API
WordPress REST APIWordPress REST API
WordPress REST API
Igor Sazonov
 
Нельзя просто так взять и сделать версионирование API
Нельзя просто так взять и сделать версионирование APIНельзя просто так взять и сделать версионирование API
Нельзя просто так взять и сделать версионирование API
EatDog
 

What's hot (20)

C# Desktop. Занятие 15.
C# Desktop. Занятие 15.C# Desktop. Занятие 15.
C# Desktop. Занятие 15.
 
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
 
Пользователь точно оценит! Повышение производительности мобильных приложений ...
Пользователь точно оценит! Повышение производительности мобильных приложений ...Пользователь точно оценит! Повышение производительности мобильных приложений ...
Пользователь точно оценит! Повышение производительности мобильных приложений ...
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
 
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
Чистая архитектура с VIPER / Сергей Крапивенский (Rambler&Co)
 
Продвинутое использование Celery — Александр Кошелев
Продвинутое использование Celery — Александр КошелевПродвинутое использование Celery — Александр Кошелев
Продвинутое использование Celery — Александр Кошелев
 
Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
 
Опыт разработки и тестирования RESTful JSON сервиса
Опыт разработки и тестирования RESTful JSON сервисаОпыт разработки и тестирования RESTful JSON сервиса
Опыт разработки и тестирования RESTful JSON сервиса
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST API
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + Retrofit
 
Реактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложенияРеактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложения
 
Илья Ефимов «IoC/DI на примере Autofac»
Илья Ефимов «IoC/DI на примере Autofac»Илья Ефимов «IoC/DI на примере Autofac»
Илья Ефимов «IoC/DI на примере Autofac»
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на Swift
 
Нейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
Нейронечёткая классификация слабо формализуемых данных | Тимур ГильмуллинНейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
Нейронечёткая классификация слабо формализуемых данных | Тимур Гильмуллин
 
Тестирование производительности систем мониторинга на платформе Microsoft SCO...
Тестирование производительности систем мониторинга на платформе Microsoft SCO...Тестирование производительности систем мониторинга на платформе Microsoft SCO...
Тестирование производительности систем мониторинга на платформе Microsoft SCO...
 
WordPress REST API
WordPress REST APIWordPress REST API
WordPress REST API
 
JS and files ver 1
JS and files ver 1JS and files ver 1
JS and files ver 1
 
Нельзя просто так взять и сделать версионирование API
Нельзя просто так взять и сделать версионирование APIНельзя просто так взять и сделать версионирование API
Нельзя просто так взять и сделать версионирование API
 

Similar to Тестирование Web API

Простой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NETПростой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NET
Mikhail Shcherbakov
 
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Andrey Rebrov
 
Виталий Каторгин, Wamba
Виталий Каторгин, WambaВиталий Каторгин, Wamba
Виталий Каторгин, Wamba
Ontico
 
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNgДело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
IT61
 
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОПЧуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Kirill Chebunin
 
Automation Functional Testing in Agile Projects
Automation Functional Testing in Agile ProjectsAutomation Functional Testing in Agile Projects
Automation Functional Testing in Agile Projects
Andrey Rebrov
 
Конкурс для разработчиков от Evernote
Конкурс для разработчиков от EvernoteКонкурс для разработчиков от Evernote
Конкурс для разработчиков от Evernote
Evernote
 
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
AvitoTech
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
DevDay
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Minktyomo4ka
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорьdrupalconf
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionAlbina Tiupa
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionAlbina Tiupa
 
Cоздание приложений со знанием Perl
Cоздание приложений со знанием PerlCоздание приложений со знанием Perl
Cоздание приложений со знанием Perl
Anatoly Sharifulin
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов ИгорьPVasili
 
Python Development process in Yandex
Python Development process in YandexPython Development process in Yandex
Python Development process in Yandex
aviatakz
 
Процессы разработки в Яндексе
Процессы разработки в ЯндексеПроцессы разработки в Яндексе
Процессы разработки в Яндексе
Andrey Kazarinov
 
RESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentationRESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentation
Mikhail Shcherbakov
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
Timur Shemsedinov
 

Similar to Тестирование Web API (20)

Простой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NETПростой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NET
 
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
 
Виталий Каторгин, Wamba
Виталий Каторгин, WambaВиталий Каторгин, Wamba
Виталий Каторгин, Wamba
 
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNgДело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
 
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОПЧуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОП
 
Automation Functional Testing in Agile Projects
Automation Functional Testing in Agile ProjectsAutomation Functional Testing in Agile Projects
Automation Functional Testing in Agile Projects
 
Конкурс для разработчиков от Evernote
Конкурс для разработчиков от EvernoteКонкурс для разработчиков от Evernote
Конкурс для разработчиков от Evernote
 
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
Rempl — крутая платформа для крутых инструментов - Роман Дворнов (Avito)
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Mink
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с Codeception
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с Codeception
 
Tdd php
Tdd phpTdd php
Tdd php
 
Cоздание приложений со знанием Perl
Cоздание приложений со знанием PerlCоздание приложений со знанием Perl
Cоздание приложений со знанием Perl
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
 
Python Development process in Yandex
Python Development process in YandexPython Development process in Yandex
Python Development process in Yandex
 
Процессы разработки в Яндексе
Процессы разработки в ЯндексеПроцессы разработки в Яндексе
Процессы разработки в Яндексе
 
RESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentationRESTful API: Best practices, versioning, design documentation
RESTful API: Best practices, versioning, design documentation
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
 

Тестирование Web API

  • 2. Особенности моего проекта — Большая зависимость от БД — Зависимость от внешних сервисов • Push сообщения • Email • Сокращение ссылок • Платежи Webapi Внешние сервисыБД Внутренние сервисы
  • 3. Боль тестирования — Тестирование контроллеров • Много мокать • Сложная поддержка • Не тестируются запросы к БД — Интеграционные тесты • Малое покрытие • Очень трудно тестировать сложные сценарии — Ручное тестирование • Долго • Никто не делает регресс
  • 4. Доклад про TestServer — озарение! — Выглядит просто — Решил попробовать — Сделал предположения • можно мочить • можно дебажить в том же процессе (в одной студии)
  • 5. Внедрение TestServer — Готовая реализация под .Net Core, а у меня классический .Net — nUnit — Внедрял параллельно разработке
  • 6. Предметная область демо-проекта — Есть группы — У групп есть пользователи — У пользователей есть роли: владелец, юзер и модератор — Владелец может назначать модераторов — Владелец и модератор могут публиковать заметки
  • 7. Структура тестов Test API client Requester API server
  • 8. [OneTimeSetUp] public void OneTimeSetUp() { ApiServer = new ApiServer(); var requester = ApiServer.GetRequester(); ApiClient = new ApiClient(requester); } [OneTimeTearDown] public void OneTimeTearDown() { ApiServer.Dispose(); } [SetUp] public void Setup() { ApiServer.Reset(); } Test API client Requester API serverTest
  • 9. — Администратор создаёт группу — Пользователь вступает в группу — Администратор назначает пользователя модератором — Пользователь может создавать заметки Test API client Requester API serverTest
  • 10. Test API client Requester API serverTest var adminToken = await ApiClient.Account.GetToken("123", "456"); var userToken = await ApiClient.Account.GetToken("aaa", "bbb"); var groupOwner = await ApiClient.Group.CreateGroup(adminToken, new CreateGroupDto { Name = "Тестовая группа " + DateTime.UtcNow.Ticks }); GroupMember userMember = await ApiClient.Group.Join(userToken, groupOwner.Group.Id); await ApiClient.Group.SetModerator(adminToken, groupOwner.Group.Id, userMember.Id); var note = await ApiClient.Group.AddNote( userToken, groupOwner.Group.Id, "Заметка от модератора"); Assert.That(note, Is.Not.Null); Assert.That(note.Text, Is.EqualTo("Заметка от модератора"));
  • 11. public class GroupApiClient { private readonly IHttpRequester _requester; public GroupApiClient(IHttpRequester requester) { _requester = requester; } public async Task<GroupMemberDto[]> GetGroups(string token) { return await _requester.GetAsync<GroupMemberDto[]>("/api/group", token); } public async Task<GroupMemberDto> CreateGroup(string token, CreateGroupDto dto) { return await _requester .PostAsync<CreateGroupDto, GroupMemberDto>("/api/group", token, dto); } Test API client Requester API serverAPI client
  • 12. public HttpClient CreateClient(string token = null) { var client = new HttpClient(_handler) {BaseAddress = _baseAddress}; if (token != null) client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return client; } public async Task<TResult> GetAsync<TResult>(string url, string token) { using (var client = CreateClient(token)) { var response = await client.GetAsync(url); await CheckStatusCode(response); return await Deserialize<TResult>(response); } } Test API client Requester API serverRequester
  • 13. public class ApiServer : IDisposable { public TestServer TestServer { get; } private TestStartup Startup { get; } public ApiServer() { Startup = new TestStartup(); TestServer = TestServer.Create(app => { Startup.Configuration(app); }); } public IHttpRequester GetRequester() { return new HttpRequester(TestServer.Handler, TestServer.BaseAddress); } public void Reset() { //Логика сброса моков перед каждым тестом } Test API client Requester API serverAPI server
  • 14. public class TestStartup : Startup { protected override WindsorContainer CreateWindsorContainer() { var container = base.CreateWindsorContainer(); return container; } protected override IncludeErrorDetailPolicy GetErrorDetailPolicy() => IncludeErrorDetailPolicy.Always; } Test API client Requester API serverAPI server
  • 15. Профит — Тесты стали похожи на реальные пользовательские сценарии — Отладка в одной студии — Сокращение цикла отладки — Внешние зависимости перестали мешать тестировать — Уверенность в работоспособности системы увеличилась
  • 16. Дальнейшее развитие — Единожды создавать тест сервер в памяти — Настроить запуск на TeamCity — Мокать под конкретный тест
  • 17. Спасибо за внимание! Email: rusakov@byndyusoft.com Vk: https://vk.com/id512458 GitHub: https://github.com/Mblkolo Telegram: https://t.me/Mblkolo

Editor's Notes

  1. Отрезать базу данных сложно, нужно очень много мокать, не будут тестироваться запросы, реальные изменения в бд Внние сервисы отрезать относительно не сложно
  2. Трудно тестировать сложные сценарии потому что есть интеграция с внешними сервисами. Можно сделать специальный флаг, но это нужно поддерживать.
  3. Предположение чем это мне полезно 15 мая был доклад от Димы
  4. Не просил у заказчика времени на внедрение, т.к. заказчик не хочет покупать QA. Делал вместе с фичами от минимального прототипа и по нарастающей Изучил Димину реализацию, получалось что так просто реализацию не скопировать, т.к. использовалось много специфичных классов. У нас уже использовался nUnit, переезд на xUnit потребовал бы времени
  5. Поток выполнения запроса. Тест обращается к апи клиенту, который через реквестер вызывает методы апи сервера.
  6. Настройки и моки
  7. Настройки и моки