Нужна уверенность в модульных тестах и ​​лучших практиках - PullRequest
2 голосов
/ 14 ноября 2010

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

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

Типичные вопросы, которые я получаю:

  • Я не вижу ничего плохого в Тестирование интеграции? Я сказал им медленно, вы никогда не должны делать это.

    Если я не могу проверить приватный метод (я знаю MSTest делает) какой смысл в тестирование? Все мои важные методы частный.

    Не вижу смысла настраивать ожидание и вернуть результат, который радует тест?

    Какие типовые юнит-тесты вы должен выступать в каждом слое? Должен ты тестируешь только на граничных уровнях?

    Как проверить возврат хранимой процедуры ожидаемые результаты?

Как вы думаете, приведенные ниже тесты имеют какой-то смысл для вас? Какой тип теста вы обычно проводите на каждом слое? Какие-нибудь примеры с кодом?

Я делаю 3 вида тестов

1) Тесты ViewModel.

2) Wcf Проверяет, издеваясь над сервисом

3) Wcf Integratontest, но издевается над Dal

Это то, что вы делаете? Можете ли вы исправить меня, если вы считаете, что это неправильно. Можете ли вы улучшить их?

Тесты ViewModel свойство изменилось и методы были названы примером ниже

      //property has changed
      [TestMethod]
      public void Should_be_able_to_test_that_customer_description_propertyChanged_was_raised()
      {
         //act
         var customerResponse=new CustomerResponse{Description = "Test"};
         var customerViewModel = new CustomerViewModel(customerResponse);
         var eventWasRaised = false;

         customerViewModel.PropertyChanged += (sender, e) => eventWasRaised = e.PropertyName == "Description";
         customerViewModel.Description = "DescriptionTest";


         Assert.IsTrue(eventWasRaised, "PropertyChanged event was not raised correctly.");
      }

        //Testing a method on the view model has been called
        [Test]
        public void Should_be_able_to_test_that_insert_method_on_view_Model_has_been_executed()
        {
            var mock = new Mock<IRepository>();
            var employeeVm = new EmployeeVM(mock.Object) {Age = 19};
            employeeVm.SaveCommand.Execute(null);
            mock.Verify(e=>e.Insert(It.IsAny<Employee>()));
        }

Модульные тесты WCF

// Тест 1 издевательский над сервисом

      [TestMethod]
      public void Should_be_able_to_verify_getCustomer_has_been_called)
      {
         var mockService = new Mock<ICustomer>();
         var expectedCustomer=new Customer{Id=1,Name="Jo"};
         mockService.Setup(x => x.GetCustomer(It.IsAny<int>())).Returns(expectedCustomer);

         var customerViewModel = new customerViewModel(mockService.Object);
         customerViewModel.GetCustomer.Execute(null);

         mockService.Verify(x=>x.GetCustomer(),Times.AtLeastOnce());
      }

      //Test 2 mocking the repository
      [TestMethod]
      public void Should_be_able_to_verify_getCustomer_has_been_called_on_the_service)
      {
         var mockRepository = new Mock<IRepositoryCustomer>();
         var expectedCustomer=new Customer{Id=1,Name="Jo"};
         mockRepository.Setup(x => x.GetCustomer(It.IsAny<int>())).Returns(expectedCustomer);

         var customerService = new CustomerService(mock.Object);
         customerService.GetCustomer(1);

         mockRepository.Verify(x=>x.GetCustomer(),Times.AtLeastOnce());
      }

Ответы [ 2 ]

3 голосов
/ 14 ноября 2010

Хорошо, давайте посмотрим, смогу ли я ответить

I dont see anything wrong with integration Testing? I told them is

медленно, вы никогда не должны это делать.

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

Вам также нужны другие (медленные) тесты, которые проверяют, являются ли настоящие коллаборации (например,DAL) вести себя в соответствии с договором.(Я обычно называю эти интеграционные тесты сейчас)

Если я не могу протестировать privateMethod (я знаю, что MSTest делает), какой смысл в тестировании?Все мои важные методы являются частными.

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

Я не вижу смысла устанавливать ожидание ивернуть результат, который удовлетворяет тесту?

См. ответ № 1 - вы предполагаете, что реальные зависимости будут вести себя в соответствии с согласованным контрактом.Это позволяет вам сосредоточиться на коде, который вы пишете, используя зависимости.

Какие типовые модульные тесты вы должны выполнять на каждом слое?Следует ли проводить тестирование только на граничных уровнях?

Юнит-тесты должны проверять объекты, Приемочные тесты проверяют, что все объекты работают вместе, когда они включены друг в друга

Как проверитьмоя хранимая процедура возвращает ожидаемые результаты?

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

1 голос
/ 14 ноября 2010

Тесты, которые вы написали, - хорошее начало!Испытывая это, тренируясь и отрабатывая то, что работает, а что нет, то, как любой, кто является «гуру», становится одним из первых.(Я еще не встречал «гуру»; просто люди с годами практики).

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

Интеграционное тестирование действительно медленное, да.

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

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

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

Тестирование частных методов должно быть ненужным.Однако ...

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

Кроме того, не тестируйте методы.Опишите каждый аспект поведения вашего класса, покажите, почему оно ценно, и приведите несколько примеров его использования.Поведение может включать в себя более одного метода.Например, list.isEmpty требует, чтобы мы тоже работали с list.add;именно взаимодействие между ними важно для вещей, использующих list.

Именно поэтому мы не тестируем частные методы - потому что они не приносят пользы классу, использующему их самостоятельно.

Названия ваших тестов могут помочь отразить это.Подумайте: «Моя модель представления должна ...», а затем подумайте, как она обеспечивает ценное поведение, которое она делает.Например, я бы сформулировал ваш первый тест как «Моя модель представления должна уведомлять слушателей, что описание изменилось», поэтому ShouldNotifyListenersThatTheDescriptionChanged.

Вместо , устанавливающего ожидание , считайте, что вашУ класса есть несколько сотрудничающих классов.

Некоторые из них предоставляют классу информацию - контексты, которые меняют его поведение и приводят к различным результатам.Некоторые из них делают работу для класса.Первые - это «заглушки», а вторые - «издевательства» (терминология здесь смешана во всем бизнесе).

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

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

Насмешки - всего лишь полезный способ сделать это.

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

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

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

...