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

Примеры модульных испытаний?

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

Можете ли вы привести несколько примеров, когда модульные тесты могут использоваться в контексте веб-разработки переднего или заднего конца?

4b9b3361

Ответ 1

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

Модульные тесты могут сначала немного запутываться. Иногда не всегда понятно, как тестировать что-то или что цель теста.

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

Первое, что я использую модульные тесты, - проверить, работает ли какой-либо метод, как я ожидаю, для всех случаев. Недавно я написал метод проверки номера телефона для моего сайта. Я принимаю любые входы от 123-555-1212, (123) 555-1212 и т.д. Я хочу убедиться, что мой метод проверки работает для всех возможных форматов. Без unit test я был бы вынужден вручную вводить каждый другой формат и проверять правильность записи. Это очень утомительно и подвержено ошибкам. Позже, если кто-то внесет изменения в код проверки телефона, было бы неплохо, если бы мы могли легко проверить, чтобы убедиться, что ничего не сломалось. (Возможно, мы добавили поддержку кода страны). Итак, вот тривиальный пример:

public class PhoneValidator
{
    public bool IsValid(string phone)
    {
          return UseSomeRegExToTestPhone(phone);
    }
}

Я мог бы написать unit test следующим образом:

public void TestPhoneValidator()
{
     string goodPhone = "(123) 555-1212";
     string badPhone = "555 12"

     PhoneValidator validator = new PhoneValidator();

     Assert.IsTrue(validator.IsValid(goodPhone));
     Assert.IsFalse(validator.IsValid(badPhone));
}

Те 2 строки подтверждения подтвердят, что значение, возвращенное из IsValid(), истинно и false соответственно.

В реальном мире у вас, вероятно, будет много и много примеров хороших и плохих телефонных номеров. У меня около 30 номеров телефонов, которые я тестирую. Простое выполнение этого unit test в будущем сообщит вам, не сломалась ли логика проверки вашего телефона.

Мы также можем использовать модульные тесты для имитации вещей вне нашего контроля.

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

public class AccountServices
{
   private IBankWebService _webService = new BankWebService();

   public string RegisterUser(string username, string creditCard)
   {
        AddUserToDatabase(username);

        bool success = _webService.BillUser(creditCard);

        if (success == false)
           return "Your credit card was declined"
        else
           return "Success!"

    }
}

Здесь модульное тестирование очень запутанно и не очевидно. Что должен испытать этот метод? Во-первых, было бы очень приятно, если бы мы могли проверить, что если сбой выставления счета не удалось, было возвращено соответствующее сообщение об ошибке. Как оказалось, используя макет, есть способ. Мы используем то, что называется Inversion of Control. Прямо сейчас AccountServices() отвечает за создание объекта BankWebService. Пусть пусть вызывающий из этого класса снабжает его, хотя:

public class AccountServices
{
   public AccountServices(IBankWebService webService)
   {
       _webService = webService;
   }

   private IBankWebService _webService;

   public string RegisterUser(string username, string creditCard)
   {
        AddUserToDatabase(username);

        bool success = _webService.BillUser(creditCard);

        if (success == false)
             return "Your credit card was declined"
        else
           return "Success!"

    }
}  

Поскольку вызывающий объект отвечает за создание объекта BankWebService, наш unit test может создать поддельный:

public class FakeBankWebService : IBankWebService
{
    public bool BillUser(string creditCard)
    {
        return false; // our fake object always says billing failed
    }
}

public void TestUserIsRemoved()
{
    IBankWebService fakeBank = FakeBankWebService();

    AccountServices services = new AccountServices(fakeBank);

    string registrationResult = services.RegisterUser("test_username");

    Assert.AreEqual("Your credit card was declined", registrationResult);
}

Используя этот поддельный объект, в любое время вызывается наш банк BillUser(), наш поддельный объект всегда будет возвращать false. Наш unit test теперь проверяет, что, если вызов в банк завершился неудачно, RegisterUser() вернет правильное сообщение об ошибке.

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

public string RegisterUser(string username, string creditCard)
{
    AddUserToDatabase(username);

    bool success = _webService.BillUser(creditCard);

    if (success) // IT BACKWARDS NOW
        return "Your credit card was declined"
    else
        return "Success!"

}

Теперь, когда ваш счет не работает, ваш метод RegisterUser() возвращает "Успех!". К счастью, у вас есть unit test. Этот unit test будет терпеть неудачу, потому что он больше не возвращает "Ваша кредитная карта была отклонена".

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

Как только вы посмотрите на различные издевательские рамки, есть еще более мощные вещи, которые вы можете сделать. Вы можете проверить, вызваны ли ваши поддельные методы, вы можете проверить количество раз, когда был вызван метод, вы можете проверить параметры, с которыми были вызваны методы, и т.д.

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

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

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