Практика рефакторинга кода, проверенного модулем - PullRequest
4 голосов
/ 17 июля 2010

Предположим, у меня есть такая функция:

public void AddEntry(Entry entry)
{
    if (entry.Size < 0)
        throw new ArgumentException("Entry size must be greater than zero");
    DB.Entries.Add(entry);
}

И соответствующий юнит-тест:

[TestMethod]
[ExpectedException(typeof(ArgumentException), "Entry size must be greater than zero")]
public void AddEntry_TermSizeLessThanZero_ThrowException()
{
    Entry e = new Entry(-5);

    AddEntry(e);
}

А затем я реорганизую код проверки:

public void AddEntry(Entry entry)
{
    Validate(entry);
    DB.Entries.Add(entry);
}

public void Validate(Entry entry)
{
    if (entry.Size < 0)
        throw new ArgumentException("Entry size must be greater than zero");
}

В модульном тесте больше не описывается код проверки.

Что лучше всего сделать в этом случае? Должен ли я просто оставить Validate () для тестирования через AddEntry?

Редактировать: чтобы уточнить, предположим, у меня была причина сделать общедоступный код с рефрактором (немного надуманным в этой ситуации), я хотел бы дублировать тестовый код, чтобы он был тщательным?

Ответы [ 3 ]

6 голосов
/ 18 июля 2010

Поскольку вы сделали метод Validate() общедоступным членом вашего объекта (по какой-либо причине), вам, безусловно, следует добавить отдельный тест для него.Тест для AddEntry должен оставаться на месте.

Модульный тест должен только проверять интерфейс блока и не должен предполагать какие-либо детали реализации.Так что в этом случае вы должны оставить свой тест для AddEntry на месте, так как он описывает поведение вашего интерфейса.Но вы не должны предполагать или проверять, что AddEntry() вызывает Validate().

2 голосов
/ 18 июля 2010

По мере развития этого кода есть две возможности:

  1. Validate() остается простым и действует как частный помощник, о котором внешние пользователи (включая тесты) не должны знать. В этом случае Validate() не должен иметь своих собственных тестов, а вместо этого должен проверять свое поведение с помощью других методов, которые его вызывают.

  2. Validate() становится настолько сложным, что вам приходится дублировать много тестового кода, чтобы убедиться, что он вызывается в каждом месте, где он должен быть. В этом случае я хотел бы рассмотреть извлечение интерфейса + класс для выполнения проверки. Validate() может быть затем тщательно проверен в его новом доме, а поддельный IValidator (или любой другой) может использоваться в вашем тесте AddEntry, утверждая, что Validate() вызывается при необходимости.

2 голосов
/ 18 июля 2010

На данный момент я бы не стал добавлять тест в Validate (), поскольку этот код уже обработан существующим тестом.Мне нравится этот тест, так как он близко соответствует требованиям класса.

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

Когда Validate () имеет несколько вызывающих абонентов и Validate () начинает тестировать несколько условий, вам, вероятно, понадобится:

  • 1 тест Validate () для каждого условия проверки
  • 1 тест на вызов для Validate
    • вы можете проверить, кто-то вызывает Validate, передав одно из условий сбоя
      • Недостатком этого подхода является менее поддельная абстракция
      • Недостатком является то, что все тесты могут стать недействительными, если критерии Validate () изменятся
      • рассмотреть возможность помещения кода, генерирующего неверный ввод, в тестслужебный метод
    • вы также можете проверить, что кто-то вызывает Validate, передав имитирующий объект для валидатора
      • Преимуществом этого подхода является разделение того, что проверяется, и того, кто делаетпроверка, делая тесты более надежными по сравнению с некоторыми изменениями
      • недостаток - еще один уровень абстракции, делающийкод более сложный

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

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