Мышление OO с TDD - с чего начать? - PullRequest
3 голосов
/ 25 июня 2009

Я пытаюсь улучшить свои навыки TDD / OO и каждый раз, когда я пытаюсь использовать TDD, чтобы повлиять на дизайн, я сталкиваюсь со стеной, с которой начать.

Вот мой пример использования / история:

Определите подмножество клиентов, которые должны быть рассмотрены. Начните обзор для них и отправьте пару писем.

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

Я хочу, чтобы код домена был в центре внимания, и я хочу, чтобы он тестировался.

Так что же проще всего сделать в этом случае?

Полагаю, мне нужен мой список клиентов. У меня уже есть клиентский объект (в стиле CSLA), хотя в нем много зависимостей, которые сложно сломать. Я предполагаю, что у меня мог быть объект ClientReviewClients и проверка, что я получаю правильное количество обзоров. Есть ряд факторов, которые мне нужно учитывать, поэтому это не кажется простым. И вообще, как мне издеваться над тем, что у меня есть 10 отзывов из 20 клиентов?

Может ли кто-нибудь помочь мне в моем пути?

Ответы [ 3 ]

4 голосов
/ 25 июня 2009

Здесь - я начну вас с пары тестов:

class IdentifyClientsDueForReview {
   public void CanStartSearch() {
      var s = new ClientSearcher();
   }

   public void CanSearchClients() {
      var s = new ClientSearcher();
      var r = s.Find(c => c.Id == 1);
      Assert.IsNotNull(r);
   }

   public void Finds10Clients() {
      var db = new MockDB();
      // Clients that need review
      for (int i = 0; i < 10; i++) {
         db.Add(new Client() { 
            NextReview = DateTime.Today.SubtractDays(i) 
         });
      }
      // Clients that don't need review
      for (int i = 0; i < 10; i++) {
         db.Add(new Client() { 
            NextReview = DateTime.Today.AddDays(i) 
         });
      }

      var s = new ClientSearcher(db);
      var r  = s.Find(c => c.NextReview <= DateTime.Today);
      Assert.AreEqual(10, r.Count);
   }
}

Он построен с учетом Linq To Sql или аналогичного бэкэнда ORM - иначе вы, вероятно, отказались бы от метода Find и имели бы некоторые жестко закодированные FindBy<Criteria> методы.

Это должно дать вам класс ClientSearcher, который использует интерфейс для обращения к базе данных. И MockDB, и ваш RealDB класс будут реализовывать этот интерфейс.

1 голос
/ 25 июня 2009

Я не знаком с C #, поэтому не могу помочь вам с ложным вопросом, полагаю, это зависит от вашей среды тестирования.

Я делаю много TDD, и в целом мой подход - это подход сверху вниз. Сначала я думаю просто о коде, который хочу написать, чтобы что-то сделать. Допустим, в вашем примере у меня есть класс Client и я хочу сделать что-то вроде: Client.initiate_reviews

Поэтому я пишу тест, который устанавливает контекст (пара клиентов, некоторые с отзывами). Затем вызовите Client.initiate_reviews, а затем запишите все утверждения, чтобы определить, выполнил ли он свою работу, то есть для подмножества клиентов, которые должны были быть проверены, выполняется ли сейчас проверка и отправлены ли все ожидаемые результаты?

В зависимости от количества побочных эффектов, которые имеет метод, может быть целесообразно разделить его на несколько тестов.

Затем я захожу в клиентский класс, определяю метод и думаю о коде, который я хотел бы написать в нем. Может быть так:

clients = Client.find_all_due_for_review
for_each client in clients {
    review = Review.start_new_for(client)
    Letter.send_for_review(review)
}

Затем я бы написал тесты для методов, вызываемых в этом методе, которые я должен реализовать. Find_all_due_for_review не имеет побочных эффектов, но возвращает что-то, поэтому, конечно, вы можете проверить возвращаемое значение здесь и, возможно, ничего не изменилось. И повторять до тех пор, пока не пройдёт первый тест.

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

Надеюсь, это поможет!

1 голос
/ 25 июня 2009

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

Что касается количества клиентов, нуждающихся в рецензировании, мне было бы не особенно интересно знать, что мне нужно 10 из 20, нуждающихся в рецензировании, но для конкретного клиента я правильно решаю, нуждается ли этот клиент в рецензии. на основании моих бизнес-правил?

Вам может пригодиться серия из двух частей "TDD / Использование объектов-имитаторов с CSLA.Net":

Вы упомянули сложные зависимости, и я настоятельно рекомендую Эффективно работать с устаревшим кодом от Michael Feathers. Книга полна консервативных методов нарушения зависимостей , полезных для тестирования кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...