Ещё чуть-чуть о тестах

18 окт. 2011 г. | | |

И еще одна небольшая заметка о TDD, точнее о том, что такое тест в контексте TDD.
Начинающие тэдэдэшники часто переусердствуют, стараясь тестировать всё и вся, забывая, что тест в TDD - это небольшой метод, проверяющий конкретное бизнес-правило. Акцент тут следует сделать на бизнес-правилах, они специфицируют поведение приложения, именно их нужно тестировать. С помощью TDD мы разрабатываем бизнес-логику. Не следует тестировать работу с БД, с файловой системой, сетевое взаимодействие - это уже совсем другой вид тестирования. Это интеграционные тесты. TDD позволяет нам быстро разрабатывать бизнес-логику, подтверждая работоспособность (или наоборот) кода мгновенным фидбеком. Если приходится специально что-то настраивать, чтобы запустить тест, и настройка занимает больше времени, чем написание самого теста, следует насторожиться. Метод для теста должен быть черным ящиком: известно только, что на входе, нужно удостовериться в правильности того, что на выходе.
В реальной жизни часто бывает так, что нужно взять выборку из БД и подсунуть данные методу для выполнения сложных расчетов. Для тестирования таких методов придумали Mocks, Fackes, Dummies & Stubs. Все эти технологии позволяют абстрагироваться от уровня физического взаимодействия, генерируя методы-заглушки. А методы заглушки возвращают тот набор данных, который им подсовываем. Чтобы было понятнее, вот простенький пример с Mock-библиотекой Moq.
Например, нам нужно взять из БД данные о продажах и посчитать средние значения по дням и неделям. Как мы будем это делать?
[Fact]
public static shouldCalculateAvarageStatistic()
{
     var datasource = new Moq<IDataSource>();
     datasource.Setup(source=>source.GetMonthSales(

              new   Month(Monther.October)).Returns(
                    new List<Product>(){
                        new Product(){Price=12.50}, 

                        new Product(){Price=12.50}, 
                        new Product(){Price=25.0}, 
                        new Product(){Price=74}
                    });
     var counter = new Counter(datasource);
     var stats = counter.GetAvarageStats(new Month(Monther.October));
     Assert.Equal( 31.0, stats.ProfitPerWeek);
     Assert.Equal( 4.0, stats.ProfitPerDay);
}


Класс, который получился в итоге:

class Counter
{
     IDataSource datasource;
     public Counter(IDataSource _datasource)
     {
          datasource = _datasource;
     }
     public IStatistic GetAvarageStats(Month month)
     {
          var data = datasource.GetMonthSales(month);
          var avarage_per_day = data.Sum(product=>product.Price) / month.Days;
          var avarage_per_week = data.Sum(product=>product.Price) / month.Weeks;
          return new AvarageStatistics(avarage_per_week, avarage_per_day);
     }
}

0 коммент.:

Отправить комментарий