Держите ваш источник близко и ваши модульные тесты ближе - PullRequest
4 голосов
/ 17 марта 2009

Когда я впервые начал использовать модульные тесты, я столкнулся с двумя проблемами. Во-первых, была возможность протестировать частные методы и поля, а во-вторых, отставание в поддержании модульных тестов в актуальном состоянии, когда происходила быстрая разработка. Следовательно, я применил подход ниже для моих модульных тестов.

#if UNITTEST
using NUnit.Framework;
#endif

public class MyBlackMagic
{
   private int DoMagic()
   {
      return 1;
   }

   #if UNITTEST

   [TestFixture]
   public class MyBlackMagicUnitTest
   {
        [TestFixtureSetUp]
        public void Init()
        {
             log4net.Config.BasicConfigurator.Configure();
        }

        [Test]
        public void DoMagicTest()
        {
             Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
             Assert.IsTrue(DoMagic() == 1, "You are not a real magician!");
         }
     }

     #endif
 }

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

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

Edit:

Просто добавим пару моментов вокруг некоторых из упомянутых слабостей:

  • Код модульного тестирования никогда не повлияет на производственный код, так как флаг прекомпилятора UNITTEST будет отключен,
  • Код модульного теста не делает основной код менее читаемым, поскольку он помещается внизу каждого класса и заключен в директиву региона Visual Studio,
  • Я считаю, что внутренний класс модульного тестирования означает, что основной класс на самом деле проще, поскольку нет никаких дополнительных методов или свойств, которые должны быть доступны только для тестирования. Всегда будут случаи, когда вы захотите проверить какое-то внутреннее состояние класса как часть модульного теста рано или поздно ...

Ответы [ 7 ]

12 голосов
/ 17 марта 2009

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

Кроме того, у вас также есть зависимость (ссылка) на сборки NUnit в самом проекте. Хотя зависимость не требуется, когда вы компилируете без условного определения unit_test, это просто уродливо и ненужно.

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

Написание юнит-тестов - это больше, чем просто тестирование; речь также идет о разработке кода.

Написав сначала тест, вы подумаете об API / интерфейсе вашего класса или о том, как вы хотите использовать эти классы.

10 голосов
/ 17 марта 2009

Вы не должны тестировать закрытые методы отдельно, потому что они (должны быть!) Используются из открытых методов или, возможно, конструкторов - поэтому публичные методы зависят от частных, чтобы преуспеть в своих назначениях.

Эти открытые методы / конструкторы потерпят (должен!) Потерпеть неудачу, если частные методы не выполнят свою работу. Так что ваш подход на самом деле плохой для написания юнит-тестов.

И чтобы повторить предыдущие ответы - напишите свои модульные тесты, прежде чем писать свои методы.

7 голосов
/ 17 марта 2009

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

3 голосов
/ 17 марта 2009

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

Однако, если вам нужно протестировать частных участников какого-то класса, это, вероятно, означает, что ваш класс делает много вещей. Возможно, вам лучше извлечь этих частных членов в новый класс. Затем вы можете протестировать этот новый класс напрямую с помощью его открытых методов.

1 голос
/ 17 марта 2009

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

0 голосов
/ 17 марта 2009

И как, скажите, мол, вы запускаете свои юнит-тесты на любой сборке, для которой вы установили UNITTEST в false?

Я дурацкий, ленивый разработчик TDD. Я не пишу достаточно близко к тестам, и не слишком часто запускаю их. Но даже я тестирую свои релизы.

0 голосов
/ 17 марта 2009

Логическое обоснование сохранения тестового кода в его отдельной сборке заключается в том, что тестовый код не должен использоваться пользователем. Модульные тесты предназначены только для проверки того, что код выполняет то, что ему предписано. Обычной практикой является размещение тестового кода в его собственной сборке, чтобы рабочий код не зависел от тестового кода и среды модульного тестирования.

Из этого примера кода мне не ясно, что вы пытаетесь проверить. Кажется, вы пытаетесь протестировать что-то, что не полностью изолировано от окружающей среды. Зачем вам нужен регистратор, когда тестеры xUnit могут регистрировать результаты тестов для вас?

Внутренние классы сложно проверить, потому что вам нужен общедоступный интерфейс (или абстрактный класс), который реализует внутренний класс, и вы должны проверить его вместе с классом, который его создал. Более явно модульные тесты должны проверять поведение одного конкретного класса, и если внутренний класс возвращается каким-либо способом, то вам нужно проверить, что он возвращен правильным образом.

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