Подтвердить что ты не робот

ASP.NET MVC - избыточное тестирование модулей? (ДВР)

Итак, я начинаю ловить ошибку TDD, но мне интересно, действительно ли я делаю это правильно... Кажется, я пишу A LOT тестов.

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

Например, это действия LogOn из моего AccountController:

public ActionResult LogOn(string returnUrl)
{
    if (string.IsNullOrEmpty(returnUrl))
        returnUrl = "/";

    var viewModel = new LogOnForm()
    {
        ReturnUrl = returnUrl
    };

    return View("LogOn", viewModel);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(LogOnForm logOnForm)
{
    try
    {
        if (ModelState.IsValid)
        {
            AccountService.LogOnValidate(logOnForm);

            FormsAuth.SignIn(logOnForm.Email, logOnForm.RememberMe);

            return Redirect(logOnForm.ReturnUrl);
        }
    }
    catch (DomainServiceException ex)
    {
        ex.BindToModelState(ModelState);
    }
    catch
    {
        ModelState.AddModelError("*", "There was server error trying to log on, try again. If your problem persists, please contact us.");
    }

    return View("LogOn", logOnForm);
}

Довольно самоочевидный.

Затем у меня есть следующий набор тестов

public void LogOn_Default_ReturnsLogOnView()
public void LogOn_Default_SetsViewDataModel()
public void LogOn_ReturnUrlPassedIn_ViewDataReturnUrlSet()
public void LogOn_ReturnUrlNotPassedIn_ViewDataReturnUrDefaults()
public void LogOnPost_InvalidBinding_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_InvalidBinding_DoesntCallAccountServiceLogOnValidate()
public void LogOnPost_ValidBinding_CallsAccountServiceLogOnValidate()
public void LogOnPost_ValidBindingButAccountServiceThrows_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_ValidBindingButAccountServiceThrows_DoesntCallFormsAuthServiceSignIn()
public void LogOnPost_ValidBindingAndValidModelButFormsAuthThrows_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_ValidBindingAndValidModel_CallsFormsAuthServiceSignIn()
public void LogOnPost_ValidBindingAndValidModel_RedirectsToReturnUrl()

Разве это убивает? Я даже не показывал тесты сервисов!

Какие из них (если есть) можно отбросить?

ТИА,
Чарльз

4b9b3361

Ответ 1

Все зависит от того, сколько вам нужно/нужно, и насколько надежна проблема.

Вот вопросы, которые вы должны задать себе:

  • Помогает ли это unit test реализовать изменение функции/кода, которое у меня еще нет?
  • Будет ли этот unit test помогать регрессионному тестированию/отладке этого устройства, если я вношу изменения позже?
  • Является ли код, удовлетворяющий этому unit test нетривиальным, или он заслуживает unit test?

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

string expected, actual;
TypeUnderTest target = new TypeUnderTest();
target.PropertyToTest = expected;
actual = target.PropertyToTest;
Assert.AreEqual<string>(expected, actual);

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

Я рекомендую эту статью автора ASP.net MVC Sanderson:

http://blog.codeville.net/2009/08/24/writing-great-unit-tests-best-and-worst-practises/

Ответ 2

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

В вашем примере возьмите LogOn (string returnUrl)

Первое, что вы делаете, - проверить параметр returnUrl и переустановить его по умолчанию, если оно равно null/empty. Вам действительно нужен целый unit test, чтобы убедиться, что одна строка кода происходит так, как ожидалось? Это не линия, которая может легко ломаться.

Большинство изменений, которые могут сломать эту строку, - это вещи, которые могут вызвать ошибку компиляции. В этой строке возможно изменение назначенного значения по умолчанию (возможно, позже вы решите, что "/" не является хорошим значением по умолчанию... но в вашем unit test, я уверен, вы жестко закодировали его для проверки на "/" не так ли? Итак, изменение значения потребует изменения в вашем тесте... что означает, что вы не тестируете свое поведение, вместо этого вы проверяете свои данные.

Вы можете получить тест на поведение метода, просто проведя один тест, который НЕ подает параметр. Это повлияет на вашу "установленную по умолчанию" часть процедуры, все еще проверяя, что остальная часть кода тоже хорошо себя ведет.

Ответ 3

Это похоже на меня. Да, вы напишете много Единичных тестов и, изначально, это будет казаться излишним и TBH пустой тратой времени; но придерживайтесь его, это того стоит. То, на что вы должны ориентироваться (а не только на 100% охват кода), - это 100% -ый охват функций. Однако... если вы обнаружите, что пишете много UT для одного и того же метода, возможно, что этот метод делает слишком много. Попробуйте отделить свои проблемы больше. По моему опыту, тело действия должно делать немного больше, чем создавать новый класс для выполнения реальной работы. Это тот класс, который вы действительно должны настраивать с помощью UT.

Крис

Ответ 4

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

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

Вам может понравиться эта книга.

Edit:
На самом деле - я только что нашел цитату об этом в разделе "Основы изоляции". Это о контрольных тестах (один конкретный тест), но я думаю, что идея остается в более глобальном масштабе:

Пересмотр спецификаций
Если у вашего теста слишком много ожиданий, вы можете создать тест, который ломается даже при самых легких изменениях кода, хотя общая функциональность все еще работает. Рассмотрите этот более технический не проверяя правильные вещи. Тестирование взаимодействий - это обоюдоострый меч: проверить его слишком много, и вы начинаете упускать из виду большую картину - общую функциональность; испытайте его слишком мало, и вы пропустите важные взаимодействия между объектами.

Ответ 5

100% -ый охват очень идеален, его действительно полезно, если вам нужно реорганизовать ваш код, однако, поскольку тесты будут управлять вашими спецификациями кода, чтобы убедиться, что они верны.

Я лично не 100% TDD (иногда слишком ленивый), но если вы намереваетесь делать 100%, возможно, вам стоит написать несколько тестовых помощников, чтобы отнять у них некоторое бремя для этих повторяющихся тестов. Например, напишите помощника, чтобы проверить все ваши CRUD в стандартной структуре сообщений с обратным вызовом, чтобы вы могли пройти через некоторую оценку, может сэкономить вам много времени.