Violet Tape некоторые мысли о разработке на платформе .Net

5Дек/110

Тестирование событий с помощью Moq

Вообще название статьи опять очень длинное на самом деле, что-то в духе: Тестирование сложных сценарий с событиями на примере Moq, связыванием StructureMap, построением объектов с помощью NBuilder, и проверки условий с помощью FluentAssertions. Но согласитесь, что это как-то чересчур и надо что-то выбрать одно, а то перечислять все технологии в заголовке плохо. Особенно когда рассматриваешь пример не простого приложения типа Hello World.

При тестировании real-life приложения возникает очень много вопросов по реализации и использовании технологий, которые обычно не рассматриваются в обзорных статьях, которые копипастятся друг у друга блогерами и агрегаторами статей. Надеюсь, данная статья прольет свет на некоторые аспекты использования упомянутых технологий.

18Июл/110

Assert DSL 1.1

Никто уже не отрицает полезность тестов в любой сколько-нибудь сложной системе. Без тестов очень быстро можно скатиться в хаос и проводить большую часть времени в отладчике, занимаясь поиском и отловом косвенных эффектов от изменений той или иной части приложения. Тесты важны, нужны и так далее по тексту.

По науке, тесты являются документированием системы. Грамотно написанные тесты дают понять, как работает система, как ведет себя, причем читаться все это должно как готовая спецификация на поведение системы. Т.е. в идеале должен получаться связный и понятный текст. Это идеал, к которому постепенно приближаются методы тестирования, начиная от юнит тестирования и наиболее явно проявляясь в поведенческом/приемочном тестировании, когда сами тесты уже пишутся на языке бизнеса (в этом моменте вспоминаем Fitnesse).

При написании тестов не стоит скупиться на строчки кода и классы, важно только их правильно структурировать. Я считаю, что может быть вполне нормальной ситуация, когда у вас тестовый класс состоит только из одного метода – не надо этого стесняться, это гораздо лучше, чем классы на 20 экранов. HD экранов.

В общем, все должно быть направлено на максимальную ясность и четкость тестов, чтобы явно было видно все взаимосвязи. Чтобы можно было восстановить логику программы по одним лишь тестам. В дело читабельности пойдет не только Assert DSL (Domain Specific Language), но и именование файлов, подход Arrange Act Assert. Все это не новые подходы как оказывается, но широкой известности пока не получившие, судя по тому, что я вижу в окружающих меня проектах. Да и сам я натолкнулся на новые темы случайно, изучая исходные коды StructureMap.

Чтобы не томить, сразу расскажу какие основные шаги предлагаются для улучшения тестов:

  • Именовать тестовые файлы по основному методу, который тестируется.
  • Использовать DSL  для создания объектов, чтобы методы делать максимально лаконичными.
  • Стараться писать тесты в стиле «один тестовый метод – один assert».
  • Структурировать внутренности теста.
  • Создать и использовать Assert DSL.

Думаю что для большинства многие перечисленные пункты не новость, и почти все они применяются в реальной разработке.

Метки записи: , , Читать полностью
16Янв/101

Domain Specific Language для TDD

Domain Specific Language (DSL) – это язык специального назначения, который предназначен для решения какой-либо задачи в терминах самой задачи.

DSL - это не какой-то новый язык программирования в общем смысле этого слова. Вы создаете этот язык путем определения домена и разрешенных операций над доменными сущностями. Если вы разрабатываете приложения по философии Domain Driven Design, у вас в целом получается DSL  автоматически (но конечно не такой красивый, как если бы вы это делали целенаправленно). Это такой положительный побочный результат. Вы создаете правила и следуете им, так как они делают решение задачи легче. Вместо кучи строк кода, которые могут менять внутреннее состояние объекта, посылать сообщения, проверять значения и условия – вы пишете один оператор, который является значимым для задачи, а весь инфраструктурный код прячется.

DSL  должен быть декларативным и, по возможности, «текучим» (fluent interface – как пример, LINQ). Т.е. целю будет сообщить ЧТО надо делать, без упоминания КАК.

DSL не зависит от конкретного языка. Можно создавать его на любом языке программирования и конечный результат будет в целом одинаков (с поправкой на синтаксис).

Кстати, SQL тоже может рассматриваться как вариант DSL, можно – так как «язык» создан для вполне определенной предметной области.

Собственно, на этом вводную часть статьи можно считать законченной. По теории можно шерстить вики и гугл, мы рассмотрим DSL на примере.

27Дек/093

DDD & TDD. Часть III

Итак, у нас есть домен с необходимыми классами и сервисами. В целом можно генерировать и обрабатывать данные в любых количествах согласно написанным сервисам. Но есть проблема, даже проблемы:

  • Как пользователь будет вводить данные;
  • Как данные будут сохраняться/загружаться.

Домен по природе и задумке своей должен быть полностью независимым и работать независимо от того, как построено взаимодействие с пользователем (WPF, WinForms, Web) и как реализован слой данных (MSSQL, MySQL, Oracle и т.д.).

Слоеные пироги

В этой части мы плавно подходим к тому, что приложение должно быть многослойное. Как минимум:

  • Домен – слой бизнес-логики. В котором описано КАК работать с данными.
  • Слой данных. В этом слое осуществляется сохранение объектов во внешние ресурсы и восстановление из внешних ресурсов в доменные объекты. Выделением этих операций в отдельный слой мы делаем приложение более гибким, т.к. можно осуществлять работу с несколькими БД, меняя их, а приложение этого даже не заметит.
  • Слой представления. В этом слое мы говорим приложению ЧТО делать с данными, т.е. вызываем в нужном порядке доменные сервисы и отдаем результат вычислений на прорисовку. Таким образом, этот слой связывает Домен и Front End.
  • Пользовательское отображение (Front End). Это пользовательский интерфейс, может быть чем угодно: консолью, win forms, web, да хоть сразу в мозг! =) Этот слой должен быть максимально «тупой», тут недолжно быть никаких изменений данных, никакой логики, как и что показывать. Слой просто делает все что ему скажут без капли самодеятельности.

После того, как определились из чего состоит приложение, надо понять как эти слои связаны между собой.

25Дек/092

DDD & TDD. Часть II

Диспозиция

По результатам предыдущего поста, у нас появились доменные классы с минимальным набором свойств и методов. Есть некоторое количество тестов на классы. Надо научиться работать с ними – т.е. написать сервисы, которые могут делать что-то более серьезное с доменными классами, например, сортировка, выборка, подсчет учеников в параллели.

Доменные сервисы

Допустим, в условиях к программе сказано,  что вам

надо определять количество классов на заданный год обучения (сколько 5ых классов или 9ых) и сколько учеников в параллели.

Подумаем, какие классы и что у нас знают:

  • «Школа» знает сколько всего вообще классов;
  • «Класс» знает сколько в нем учеников.

Кажется больше нам и не надо. Как бы я сделал на заре своего обучения? Я бы в класс School добавил метод

public int CountStudent(int classNumber) { … }

Но это плохой подход по следующим причинам:

  • У класса School увеличивается ответственность что приводит к высокой связности классов;
  • Его становится труднее поддерживать и изменять;
  • Это так же может привести к дальнейшим проблемам тестирования.
23Дек/091

DDD & TDD. Часть I

Disclaimer

Все ниже написанное специально упрощено и показывает, как с этим начать работать, всем давно практикующим специалистам просьба не быть строгим к словам. Перед чтением и экспериментами настоятельно советую поставить ReSharper.

Магические аббревиатуры

DDD – Domain Driven Design, если совсем вкратце, то это способ организации кода приложения. А организуется он таким образом, чтобы в единственной, независимой ни от чего в проекте сборке, лежала сама суть приложения.

TDD – Test Driven Development, проектирование приложения через тесты.

Обе эти практики (хотя наверно это лучше назвать уже философии) обычно идут рука об руку в моих проектах, аки сиамские братья близнецы, и мне, если честно, трудно представить себе их раздельно. Хотя конечно они могут работать и абсолютно раздельно, никто не обязывает использовать их в связке.

По DDD и TDD написано уже куча литературы различных форматов и объемов. Где-то проще, где-то запутаннее.  Исторический экскурс благополучно пропустим, кому интересно, могут погуглить книги Эрика Эванса и посетить сайт Мартина Фаулера.  Я постараюсь донести свое видение этого предмета максимально просто и доступно. Рассказать, как это помогает, работает, сопровождается и развивается.  Надеюсь, у меня все получится. =)

Но это все вкратце, теперь перейдем к более детальному рассмотрению.