Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 31.10.08 09:12
Оценка: 36 (2)
Фреймворк для удобного создания мок-объектов для тестирования Rhino Mocks очень быстро развивается. Приходится довольно часто перечитывать документацию чтобы быть "в теме".

Сегодня как раз был такой день Залез на сайт и был несказанно рад тому, что есть Quick Refference 3.3 (всего на 3 странички) для быстрого вхождения (жаль что для версии 3,3 когда уже есть 3.5...).
Для тех кто совсем не пользовался RhinoMocks можно посмотреть Quick Refference 3.1 (всего 1 страничка, самое главное).

Вот цитаты:
Создание мока:
IConnection connection = mocks.CreateMock<IConnection>();

Использование using для разделения "зоны записи мока" от "зоны использования мока":
using (mocks.Record())
{ 
...    Expect.Call(...); 
}
using (mocks.Playback())
{
  ... 
}

Примеры установки ожиданий:
Expect.Call(list.Contains(42)).Return(true);
Expect.Call(dict.TryGetValue("key", out outParam)).OutRef("value").Return(true);

Запись ограничений на параметры:
Expect.Call(file.Read(null, 0, 0)) 
    .Constraints(Property.Value("Length", 4096), Is.Equal(0), Is.GreaterThan(0) && Is.LessThan(4096));



P.S. Еще есть описание версии 3.5 (и не только ее), но уже не совсем quick: http://ayende.com/wiki/Rhino+Mocks+3.5.ashx

СУВ, Aikin
Re: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 14.11.08 21:47
Оценка: 6 (1)
Мне кажется, record-replay уже морально устарел: на дворе век Arrange-Act-Assert. По крайней мере, я сейчас потихоньку переключаюсь на это дело, и тесты становятся значительно чище и понятнее.

По поводу синтаксиса можно посмотреь блог ayende и группу google про rhino mocks.

ulu

Здравствуйте, Aikin, Вы писали:

A>Фреймворк для удобного создания мок-объектов для тестирования Rhino Mocks очень быстро развивается. Приходится довольно часто перечитывать документацию чтобы быть "в теме".


A>Сегодня как раз был такой день Залез на сайт и был несказанно рад тому, что есть Quick Refference 3.3 (всего на 3 странички) для быстрого вхождения (жаль что для версии 3,3 когда уже есть 3.5...).

A>Для тех кто совсем не пользовался RhinoMocks можно посмотреть Quick Refference 3.1 (всего 1 страничка, самое главное).

A>Вот цитаты:

A>Создание мока:
A>
A>IConnection connection = mocks.CreateMock<IConnection>();
A>

A>Использование using для разделения "зоны записи мока" от "зоны использования мока":
A>
A>using (mocks.Record())
A>{ 
A>...    Expect.Call(...); 
A>}
A>using (mocks.Playback())
A>{
A>  ... 
A>}
A>

A>Примеры установки ожиданий:
A>
A>Expect.Call(list.Contains(42)).Return(true);
A>Expect.Call(dict.TryGetValue("key", out outParam)).OutRef("value").Return(true);
A>

A>Запись ограничений на параметры:
A>
A>Expect.Call(file.Read(null, 0, 0)) 
A>    .Constraints(Property.Value("Length", 4096), Is.Equal(0), Is.GreaterThan(0) && Is.LessThan(4096));
A>



A>P.S. Еще есть описание версии 3.5 (и не только ее), но уже не совсем quick: http://ayende.com/wiki/Rhino+Mocks+3.5.ashx


A>СУВ, Aikin
Re[12]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 13:29
Оценка: 5 (1)
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, ulu, Вы писали:


A>>>C чего ты взял, что ulu предлагал на разбить функциональность из 3-х шагов (1 ассерт) на три теста (3 ассерта)?


ulu>>Я, кстати, это и предлагал. Если мы проверяем, что метод делает три вещи, пишем три тестовых метода на эти три вещи.

A>Да? Тогда извиняюсь

A>Весь во внимании. Как сделать тест для случая Ziaw


Не поручусь за синтаксис, но что-то вроде:


[TestFixture]
public class СкладываемЧисла {

   INumberSource aSrcMock;
   INumberSource bSrcMock;
   SomeService service;
   int result;

   [FixtureSetup]
   public void Создаем_Контекст() {
      aSrcMock = MockRepository.GenerateStub<INumberSource>();
      aSrcMock.Stub(x => x.GetNumber()).Return(1);
      bSrcMock = MockRepository.GenerateStub<INumberSource>();
      bSrcMock.Stub(x => x.GetNumber()).Return(2);
      service = new SomeService(aSrcMock, bSrcMock);

   }

   [Setup]
   public void Вызываем_Метод() {
      result = service.SomeMethod();
   }

   [Test]
   public void Результат_должен_равняться_сумме_аргументов() {
      Assert.AreEqual(3, result);
   }
   [Test]
   public void ПервыйАргумент_был_получен_из_aSrcMock() {
      aSrcMock.AssertWasCalled( x => x.GetNumber());
   }
   [Test] -- и второй аналогично
}
tdd aaa
Пример кода + презентация от Ayende
От: Aikin Беларусь kavaleu.ru
Дата: 31.10.08 09:37
Оценка: 2 (1)
Лежит тут: http://ayende.com/presentations.aspx

Солюшен и презентация: Interaction Based Testing &mdash; VB.Net (там не только VB? но и CS).
Re[3]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 28.11.08 19:02
Оценка: 2 (1)
Здравствуйте, cadet354, Вы писали:

C>Здравствуйте, ulu, Вы писали:


ulu>>Мне кажется, record-replay уже морально устарел: на дворе век Arrange-Act-Assert. По крайней мере, я сейчас потихоньку переключаюсь на это дело, и тесты становятся значительно чище и понятнее.


C>что-то я не понял смысл Arrange-Act-Assert, можно поподробнее обьяснить, по примерам выходит тоже самое, что и в Moq.


Наверное, похоже на Moq, я с ним не знаком.

Вот написал тут немного про свое видение вопроса здесь.
Re[5]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 29.11.08 18:32
Оценка: -1
Здравствуйте, cadet354, Вы писали:

C>Здравствуйте, ulu, Вы писали:


C>спасибо, я так примерно и делал,( а какой был подход до этого), оказывается следовал веяниям моды ,

C>хотя вот этого:
C>

C>Как все это организовать, чтобы было понятно? Начнем с последнего. Очень важный принцип, который я очень долго игнорировал (потому, что "все и так работало") -- надо в каждом тестовом методе иметь ровно один Assert. Более того, кроме него, в сущности, ничего там не должно быть. Все остальное безжалостно тащим в Сетап.

C>А что, если какой-то тестовый метод требует другого сетапа? Верный признак того, что он сидит не в своем тестовом классе. И тут включается другое правило -- На каждый тестовый класс должен быть один общий Act. То есть, мы каждый раз в Сетапе производим тестируемое действие, а потом в тестовых методах проверяем его эффекты. Это абсолютно противоположно новичковому методу, в котором тестовый метод содержит подготовку контекста, действие, а потом проверку многочисленных результатов.

C>у меня не было, действительно в методах проверка многочисленных результатов, но не приведет ли предлагаемый метод к лавинообразному увеличению количества тестов на ровном месте?

В том-то и дело, что здесь место неровное. Юнит тест -- он не потому юнит, что проверяет функциональность какого-то одного небольшого куска системы, а потому, что он проверяет небольшой кусок функциональности. В идеале, посмотрев на название теста (и заменив подчеркивания на пробелы), можно получить кусочек ТЗ (и отрапортовать клиенту о его готовности):

[TestFixture] public class Если_нажать_на_красную_кнопку {
[Setup] public void Жмем_кнопку() {...}
[Test] public void Появится_сообщение() {...}
[Test] public void Текст_появившегося_сообщения__больше_не_жми() {...}
}

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

Есть тут другая опасность -- когда ассерты взаимозависимы. Например, мы изготавливаем коллекцию, потом проверяем, что у нее только один элемент, а потом начинаем проверять свойства этого элемента. Если что-то сломалось, и в коллекции стало ноль элементов, то все ассерты сломаются, и мы увидим кучу красных кружочков, хотя на самом деле сломался только один тест. Это называется "эффектом домино". Выход есть: в MbUnit, например, можно задать явную зависимость тестов: если один не сработал, остальные не запускаются.
Re[7]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 10:16
Оценка: +1
Здравствуйте, Ziaw, Вы писали:

Z>Что вообще дает такой подход? Какие плюсы?

Модульнось. SRP. Распределением ответственности.

Z>Допустим тестриуемый метода должен запросить два числа из разных источников и выдать их сумму.

Z>Мне нужно сделать три теста (запросил число из одного источника, запросил из другого, вернул сумму)?
Правильно, так и будет.
Z>Чем это будет лучше одного теста? Чем хуже понятно, нам надо писать три теста вместо одного и 3 раза вызывать тестируемый метод.
А почему тест который проверяет сумму двух чисел должен заморачиваться на то откуда они взялись?

И скажи, вот твой тест упал. Что именно пошло не так? Получение первого числа, второго, или сумматор глюканул?

СУВ, Aikin
Re[15]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 14:15
Оценка: +1
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, samius, Вы писали:


S>>З.Ы. Мы все же говорим о версии 3.3


Z>Вообще-то мы говорим о концепции. Я пытаюсь понять в чем прелесть ААА


http://ayende.com/Wiki/Rhino+Mocks+3.5.ashx#Arrange,Act,Assert
http://ayende.com/Blog/archive/2008/05/16/Rhino-Mocks--Arrange-Act-Assert-Syntax.aspx
Там, кстати, нет никаких рекомендаций по поводу организации методов и тестов. Все AAA делается в одном методе. И это на самом деле удобнее чем Record-Playback.
Re[14]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 15:15
Оценка: :)
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, ulu, Вы писали:


ulu>>
ulu>>[TestFixture]
ulu>>public class СкладываемЧисла {
ulu>>   [Test]
ulu>>   public void ПервыйАргумент_был_получен_из_aSrcMock() {
ulu>>      aSrcMock.AssertWasCalled( x => x.GetNumber());
ulu>>   }
ulu>>   [Test] -- и второй аналогично
ulu>>}
ulu>>

A>Как-то непонятно зачем вообще проверять вызывал ли наш метод сервис или нет (я вообще стараюсь все свести к black box testing). Но подход интерсеный.

A>Спасибо.


Это совершенно отдельная дискуссия, про Interaction vs State testing, можно поспорить, но надо готовить пену у рта
Re: Пример кода + презентация от Ayende
От: syrompe  
Дата: 05.11.08 14:09
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Лежит тут: http://ayende.com/presentations.aspx


A>Солюшен и презентация: Interaction Based Testing &mdash; VB.Net (там не только VB? но и CS).



Также весьма интересные видео http://ayende.com/hibernating-rhinos.aspx
Re[2]: Rhino Mocks 3.3 Quick Reference
От: cadet354 Россия
Дата: 28.11.08 12:33
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Мне кажется, record-replay уже морально устарел: на дворе век Arrange-Act-Assert. По крайней мере, я сейчас потихоньку переключаюсь на это дело, и тесты становятся значительно чище и понятнее.


что-то я не понял смысл Arrange-Act-Assert, можно поподробнее обьяснить, по примерам выходит тоже самое, что и в Moq.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Rhino Mocks 3.3 Quick Reference
От: cadet354 Россия
Дата: 29.11.08 09:20
Оценка:
Здравствуйте, ulu, Вы писали:

спасибо, я так примерно и делал,( а какой был подход до этого), оказывается следовал веяниям моды ,
хотя вот этого:

Как все это организовать, чтобы было понятно? Начнем с последнего. Очень важный принцип, который я очень долго игнорировал (потому, что "все и так работало") -- надо в каждом тестовом методе иметь ровно один Assert. Более того, кроме него, в сущности, ничего там не должно быть. Все остальное безжалостно тащим в Сетап.

А что, если какой-то тестовый метод требует другого сетапа? Верный признак того, что он сидит не в своем тестовом классе. И тут включается другое правило -- На каждый тестовый класс должен быть один общий Act. То есть, мы каждый раз в Сетапе производим тестируемое действие, а потом в тестовых методах проверяем его эффекты. Это абсолютно противоположно новичковому методу, в котором тестовый метод содержит подготовку контекста, действие, а потом проверку многочисленных результатов.

у меня не было, действительно в методах проверка многочисленных результатов, но не приведет ли предлагаемый метод к лавинообразному увеличению количества тестов на ровном месте?
Re[6]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 09:58
Оценка:
Здравствуйте, ulu, Вы писали:

Что вообще дает такой подход? Какие плюсы?

Допустим тестриуемый метода должен запросить два числа из разных источников и выдать их сумму. Мне нужно сделать три теста (запросил число из одного источника, запросил из другого, вернул сумму)? Чем это будет лучше одного теста? Чем хуже понятно, нам надо писать три теста вместо одного и 3 раза вызывать тестируемый метод.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[8]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 11:04
Оценка:
Здравствуйте, Aikin, Вы писали:

Z>>Что вообще дает такой подход? Какие плюсы?

A>Модульнось. SRP. Распределением ответственности.

А без лозунгов?

Z>>Чем это будет лучше одного теста? Чем хуже понятно, нам надо писать три теста вместо одного и 3 раза вызывать тестируемый метод.

A>А почему тест который проверяет сумму двух чисел должен заморачиваться на то откуда они взялись?

Тест проверяет то, что должен сделать метод. Метод должен сделать 3 вещи:
Взять из одного сервиса число a. Взять из другого число b. Сложить их и вернуть результат.

    public interface INumberSource
    {
        int GetNumber();
    }

    public class SomeService
    {
        private readonly INumberSource aSource;
        private readonly INumberSource bSource;

        public SomeService(INumberSource aSource, INumberSource bSource)
        {
            this.aSource = aSource;
            this.bSource = bSource;
        }

        public int SomeMethod()
        {
            return aSource.GetNumber() + bSource.GetNumber();
        }
    }

    [TestFixture]
    public class SomeServiceTests
    {

        MockRepository repos;
        INumberSource aSrcMock;
        INumberSource bSrcMock;
        SomeService service;

        [SetUp]
        public void Setup()
        {
            repos = new MockRepository();
            aSrcMock = repos.CreateMock<INumberSource>();
            bSrcMock = repos.CreateMock<INumberSource>();
            service = new SomeService(aSrcMock, bSrcMock);
        }

        [Test]
        public void SomeMethodTest()
        {
            using (repos.Record())
            {
                Expect.Call(aSrcMock.GetNumber()).Return(1);
                Expect.Call(bSrcMock.GetNumber()).Return(2);
            }

            using (repos.Playback())
            {
                var result = service.SomeMethod();
                Assert.AreEqual(3, result);
            }
        }
    }


Как будут выглядеть 3 теста? Чем они удобнее одного?

A>И скажи, вот твой тест упал. Что именно пошло не так? Получение первого числа, второго, или сумматор глюканул?

Тест при падении говорит, какой ассерт не сработал. Этого достаточно.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[8]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 11:10
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, Ziaw, Вы писали:


Z>>Что вообще дает такой подход? Какие плюсы?

A>Модульнось. SRP. Распределением ответственности.

Z>>Допустим тестриуемый метода должен запросить два числа из разных источников и выдать их сумму.

Z>>Мне нужно сделать три теста (запросил число из одного источника, запросил из другого, вернул сумму)?
A>Правильно, так и будет.
Z>>Чем это будет лучше одного теста? Чем хуже понятно, нам надо писать три теста вместо одного и 3 раза вызывать тестируемый метод.
A>А почему тест который проверяет сумму двух чисел должен заморачиваться на то откуда они взялись?

A>И скажи, вот твой тест упал. Что именно пошло не так? Получение первого числа, второго, или сумматор глюканул?


A>СУВ, Aikin


+1.

Если не хочется вызывать метод 3 раза, то можно отправить его в FixtureSetup. Но там лучше держать Arrange.
Re[9]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 11:50
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>+1.


Я так и не услышал плюсов подхода, только баззворды. И не увидел примера теста SomeService
Автор: Ziaw
Дата: 01.12.08
.

ulu>Если не хочется вызывать метод 3 раза, то можно отправить его в FixtureSetup. Но там лучше держать Arrange.


Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture? Не слишком ли жирно? Плюсы подхода должны быть просто громадными, чтобы оправдать такое.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[9]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 11:51
Оценка:
Здравствуйте, Ziaw, Вы писали:

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

Z>Тест проверяет то, что должен сделать метод. Метод должен сделать 3 вещи:

Z>Взять из одного сервиса число a. Взять из другого число b. Сложить их и вернуть результат.
C чего ты взял, что ulu предлагал на разбить функциональность из 3-х шагов (1 ассерт) на три теста (3 ассерта)?

Z>Как будут выглядеть 3 теста? Чем они удобнее одного?

То что ты написал это третий тест То что "Expect.Call(...)" является еще и ассертом -- дополнительный плюс Мок-тестирования (чесно говоря, спорный плюс).
Первый тест будет проверять FirstConcreteNumberSource, а второй -- SecondConcreteNumberSource

СУВ, Aikin
Re[10]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 11:56
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture?

Не на каждый метод, а на каждое состояние тестируемого объекта.

Z> Не слишком ли жирно? Плюсы подхода должны быть просто громадными, чтобы оправдать такое.

У меня тоже есть сомнения.
Re[10]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 12:02
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, Ziaw, Вы писали:


Z>>Как будут выглядеть 3 теста? Чем они удобнее одного?

A>То что ты написал это третий тест То что "Expect.Call(...)" является еще и ассертом -- дополнительный плюс Мок-тестирования (чесно говоря, спорный плюс).
Да, потому с версии 3.5 предпочтительнее является использование стабов. Ведь третий тест не должен проверять, что методы Expect.Call действительно были вызываны. И Expect.Call здесь просто информирует мокоген о том, что нужно вернуть. При использовании стабов информация о результатах используется, но факт вызова метода не проверяется.

A>Первый тест будет проверять FirstConcreteNumberSource, а второй -- SecondConcreteNumberSource

А вот это уже похоже на тестирование реализации метода. Что если SomeService не обязан вызывать эти методы в реализации метода SomeMethod? Возможно он закэшировал нужные значения в конструкторе? Т.е. проверяя факты вызова тех методов мы проверяем вовсе не контракт метода.
Re[11]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 12:11
Оценка:
Здравствуйте, Aikin, Вы писали:

Z>>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture?

A>Не на каждый метод, а на каждое состояние тестируемого объекта.

Состояние по сути является по сути еще одним аргументом к тестируемому методу. Мне трудно понять, чем оно отличается от других аргументов.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[11]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 12:12
Оценка:
Здравствуйте, samius, Вы писали:

Z>>>Как будут выглядеть 3 теста? Чем они удобнее одного?

A>>То что ты написал это третий тест То что "Expect.Call(...)" является еще и ассертом -- дополнительный плюс Мок-тестирования (чесно говоря, спорный плюс).
S>Да, потому с версии 3.5 предпочтительнее является использование стабов. Ведь третий тест не должен проверять, что методы Expect.Call действительно были вызываны. И Expect.Call здесь просто информирует мокоген о том, что нужно вернуть. При использовании стабов информация о результатах используется, но факт вызова метода не проверяется.
Угу.

A>>Первый тест будет проверять FirstConcreteNumberSource, а второй -- SecondConcreteNumberSource

S>А вот это уже похоже на тестирование реализации метода. Что если SomeService не обязан вызывать эти методы в реализации метода SomeMethod? Возможно он закэшировал нужные значения в конструкторе? Т.е. проверяя факты вызова тех методов мы проверяем вовсе не контракт метода.
Эти два теста будут находится среди тестов для FirstConcreteNumberSource и SecondConcreteNumberSource и никак не относится к SomeService
Re[12]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 12:16
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>>>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture?

A>>Не на каждый метод, а на каждое состояние тестируемого объекта.
Z>Состояние по сути является по сути еще одним аргументом к тестируемому методу. Мне трудно понять, чем оно отличается от других аргументов.
С этим сложно спорить. Хотя это и не совсем так. Раз "парамеры" находятся в разных местах (в объекте и аргументах метода), то это кому-то надо.


Вопрос: У тебя в одном тесте проверяется вызов метода с разными значениями параметров?
Re[13]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 12:26
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, Ziaw, Вы писали:


Z>>>>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture?

A>>>Не на каждый метод, а на каждое состояние тестируемого объекта.
Z>>Состояние по сути является по сути еще одним аргументом к тестируемому методу. Мне трудно понять, чем оно отличается от других аргументов.
A>С этим сложно спорить. Хотя это и не совсем так. Раз "парамеры" находятся в разных местах (в объекте и аргументах метода), то это кому-то надо.


A>Вопрос: У тебя в одном тесте проверяется вызов метода с разными значениями параметров?

Вопрос не ко мне, но я свою копейку вверну:
MbUnit умеет делать параметризованные тесты, куда можно прикручивать атрибутами либо комбинации параметров, либо провайдеры параметров. Фактически тело метода одно, но тесты создаются разные — по числу комбинаций параметров либо провайдеров.
Потому да, бывает что один метод проверяет вызов метода с разными значениями, но это физически разные тесты!
Новый NUnit тоже позволяет делать тесты с параметрами, только я еще не глядел на него пока и не знаю, трактует ли он их как разные тесты, либо как один.
Re[13]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 12:28
Оценка:
Здравствуйте, Aikin, Вы писали:

Z>>Состояние по сути является по сути еще одним аргументом к тестируемому методу. Мне трудно понять, чем оно отличается от других аргументов.

A>С этим сложно спорить. Хотя это и не совсем так. Раз "парамеры" находятся в разных местах (в объекте и аргументах метода), то это кому-то надо.

Мне проще избегать хранения состояний, чем бороться с побочными эффектами.

A>Вопрос: У тебя в одном тесте проверяется вызов метода с разными значениями параметров?


Как удобнее. Если сводится к матрице аргументы — результат, в одном. Если разные аргументы тестируют разные сценарии (вообще-то это попахивает косяком дизайна), в разных.

Я не понимаю, как SRP может давать рекомендацию тестировать один класс (соответствующий SRP) несколькими тестами. Похоже на парадокс.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 12:59
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Мне проще избегать хранения состояний, чем бороться с побочными эффектами.

Ага, а все классы у тебя простые контейнеры, а методы статические.

A>>Вопрос: У тебя в одном тесте проверяется вызов метода с разными значениями параметров?


Z>Как удобнее. Если сводится к матрице аргументы — результат, в одном.

Т.е. вот так:
[Test]
public void SomeTest()
{
    Assert.That(myOgject.MyMethod(1, 2, 3), Is.Equal(6));
    Assert.That(myOgject.MyMethod(1, 2, 0), Is.Equal(66));
    Assert.That(myOgject.MyMethod(1, 2, 3), Is.Equal(64));
    Assert.That(myOgject.MyMethod(1, 3, 8), Is.Equal(64));
    Assert.That(myOgject.MyMethod(31, 2, 2), Is.Equal(56));
    Assert.That(myOgject.MyMethod(1, 2, 78), Is.Equal(36));
    Assert.That(myOgject.MyMethod(4, 72, 3), Is.Equal(62));
    Assert.That(myOgject.MyMethod(6, 2, 2), Is.Equal(63));
}



Z>Если разные аргументы тестируют разные сценарии (вообще-то это попахивает косяком дизайна), в разных.

Ну а как же граничные значения, исключительные ситуации..?


Z>Я не понимаю, как SRP может давать рекомендацию тестировать один класс (соответствующий SRP) несколькими тестами. Похоже на парадокс.

Так, тест ([Test]) и набор тестов ([TestFixture]) это разные вещи.


P.S. Попер какой-то неконструктивизм
Re[10]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 13:01
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Здравствуйте, Ziaw, Вы писали:


A>Начнем с того, что ulu говорит совсем про другое. Про реорганизацию тестов, а не про бессмысленное увеличение их количества.

A>И с того, что я тебя неправильно понял. Я считал, что тестиреумый метод сам занимается получением этих двух чисел.

Z>>Тест проверяет то, что должен сделать метод. Метод должен сделать 3 вещи:

Z>>Взять из одного сервиса число a. Взять из другого число b. Сложить их и вернуть результат.
A>C чего ты взял, что ulu предлагал на разбить функциональность из 3-х шагов (1 ассерт) на три теста (3 ассерта)?

Я, кстати, это и предлагал. Если мы проверяем, что метод делает три вещи, пишем три тестовых метода на эти три вещи.
Re[10]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 13:07
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, ulu, Вы писали:


ulu>>+1.


Z>Я так и не услышал плюсов подхода, только баззворды. И не увидел примера теста SomeService
Автор: Ziaw
Дата: 01.12.08
.


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

Лично я увидел, что мои тесты из огромного Ball Of Mud превращаются во что-то структурированное. It Just Feels Good

Пример, простите, не стану писать -- нет времени сейчас. Но в стиле Record-replay не выйдет -- нужны новые фичи.

ulu>>Если не хочется вызывать метод 3 раза, то можно отправить его в FixtureSetup. Но там лучше держать Arrange.


Z>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture? Не слишком ли жирно? Плюсы подхода должны быть просто громадными, чтобы оправдать такое.


А что такое "жирно"? Много кода? Так его бошльше не становится, он просто разбегается по разным методам и классам.
Re[11]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 13:12
Оценка:
Здравствуйте, ulu, Вы писали:

A>>C чего ты взял, что ulu предлагал на разбить функциональность из 3-х шагов (1 ассерт) на три теста (3 ассерта)?


ulu>Я, кстати, это и предлагал. Если мы проверяем, что метод делает три вещи, пишем три тестовых метода на эти три вещи.

Да? Тогда извиняюсь

Весь во внимании. Как сделать тест для случая Ziaw
Re[10]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 13:16
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Т.е. на каждый метод тестируемого класса мы делаем свой TestFixture?


Забыл сказать. Если мы тут практикуем TDD, то у нас пока нет ни класса, ни метода, а есть требуемая функциональность. Типа:
Если выполнить операцию сложения, (Act)
-- то первый экземпляр INumberSource должен выдать число (Assert)
-- то второй экземпляр INumberSource должен выдать число (Assert)
-- то мы должны получить на выходе сумму выданных чисел (Assert)

Очевидно, что мы тут имеем в точности один TestFixture и три тестовых метода.
Re[13]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 13:45
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Не поручусь за синтаксис, но что-то вроде:


Итак, какие недостатки я вижу:

1. аргументы и результат разамазаны по коду, это не способствует читабельности
2. три метода увеличивают объем кода который требуется проанализировать при понимании теста человеком
3. на каждый метод нам нужен свой TestFixture, что не способствует пониманию назначения класса при просмотре теста

Где достоинства?
Тесты не стали более информативны, проваленный тест в обоих вариантах достаточно информативно объясняет причину провала.
Тесты не стало легче писать, не стало легче сопровождать, в где выигрыш-то?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 13:47
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Итак, какие недостатки я вижу:

4. Не представляю как в таком случае делать прогон по матрице аргументы-результат.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[13]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 13:49
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>
ulu>[TestFixture]
ulu>public class СкладываемЧисла {
ulu>   [Test]
ulu>   public void ПервыйАргумент_был_получен_из_aSrcMock() {
ulu>      aSrcMock.AssertWasCalled( x => x.GetNumber());
ulu>   }
ulu>   [Test] -- и второй аналогично
ulu>}
ulu>

Как-то непонятно зачем вообще проверять вызывал ли наш метод сервис или нет (я вообще стараюсь все свести к black box testing). Но подход интерсеный.

Спасибо.
Re[13]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 13:51
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, Aikin, Вы писали:


A>>Здравствуйте, ulu, Вы писали:


A>>>>C чего ты взял, что ulu предлагал на разбить функциональность из 3-х шагов (1 ассерт) на три теста (3 ассерта)?


ulu>>>Я, кстати, это и предлагал. Если мы проверяем, что метод делает три вещи, пишем три тестовых метода на эти три вещи.

A>>Да? Тогда извиняюсь

A>>Весь во внимании. Как сделать тест для случая Ziaw


ulu>Не поручусь за синтаксис, но что-то вроде:



ulu>
ulu>[TestFixture]
ulu>public class СкладываемЧисла {

ulu>   INumberSource aSrcMock;
ulu>   INumberSource bSrcMock;
ulu>   SomeService service;
ulu>   int result;

ulu>   [FixtureSetup]
ulu>   public void Создаем_Контекст() {
ulu>      aSrcMock = MockRepository.GenerateStub<INumberSource>();
ulu>      aSrcMock.Stub(x => x.GetNumber()).Return(1);
ulu>      bSrcMock = MockRepository.GenerateStub<INumberSource>();
ulu>      bSrcMock.Stub(x => x.GetNumber()).Return(2);
ulu>      service = new SomeService(aSrcMock, bSrcMock);

ulu>   }
ulu>}
ulu>

В случае тестирования с внешним состоянием (например БД), будет невозможно придерживаться такой схемы, т.к. FixtureSetup от других тестов сможет кое-что подпортить. Потому создание контекста все же лучше делать в Setup методе.

З.Ы. Мы все же говорим о версии 3.3
Re[14]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 13:58
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, ulu, Вы писали:


ulu>>Не поручусь за синтаксис, но что-то вроде:


Z>Итак, какие недостатки я вижу:


Z>...


Я же говорю, кому-то подходит, кому-то нет..
Re[14]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 14:02
Оценка:
Здравствуйте, samius, Вы писали:

S>З.Ы. Мы все же говорим о версии 3.3


Вообще-то мы говорим о концепции. Я пытаюсь понять в чем прелесть ААА, но из аргументов я вижу только:

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

Лично я увидел, что мои тесты из огромного Ball Of Mud превращаются во что-то структурированное. It Just Feels Good

... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[15]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 14:02
Оценка:
Здравствуйте, ulu, Вы писали:

Z>>Итак, какие недостатки я вижу:


Z>>...


ulu>Я же говорю, кому-то подходит, кому-то нет..


Где достоинства? Это религия что-ли?
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[15]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 14:22
Оценка:
Здравствуйте, Aikin, Вы писали:

A>Т.е. вот так:

Да. Можно дейстивтельно сделать матрицу соответствий, если покажется, что она читабельнее:
            var matrix = new[]
            {
                new { a1 = 1, a2 = 2, a3 = 3, result = 6},
                new { a1 = 1, a2 = 2, a3 = 0, result = 66},
                // ....
            };

            foreach (var c in matrix)
            {
                Assert.That(myOgject.MyMethod(c.a1, c.a2, c.a3), Is.EqualTo(c.result));
            }


Z>>Если разные аргументы тестируют разные сценарии (вообще-то это попахивает косяком дизайна), в разных.

A>Ну а как же граничные значения, исключительные ситуации..?
Это исключения из выделенного. Они отдельно должны тестироваться.

Z>>Я не понимаю, как SRP может давать рекомендацию тестировать один класс (соответствующий SRP) несколькими тестами. Похоже на парадокс.

A>Так, тест ([Test]) и набор тестов ([TestFixture]) это разные вещи.

Ну да. В чем мой поинт: если тестируемый класс соотвествует SRP то и TestFixture в одном классе должен соотвествовать. А вот если тест превращается в ball of mud
Автор: ulu
Дата: 01.12.08
и нам требуется несколько классов для тестирования — проблема не решается разбиением тестов, мы только скроем симптомы.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 14:27
Оценка:
Здравствуйте, samius, Вы писали:

S>В случае тестирования с внешним состоянием (например БД), будет невозможно придерживаться такой схемы, т.к. FixtureSetup от других тестов сможет кое-что подпортить. Потому создание контекста все же лучше делать в Setup методе.


Наоборот, наверное. FixtureSetup вызывается только один раз, а Setup -- перед каждым тестом.

S>З.Ы. Мы все же говорим о версии 3.3


В версии 3.3 не прокатит такая штука.
Re[15]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 14:34
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, samius, Вы писали:


S>>В случае тестирования с внешним состоянием (например БД), будет невозможно придерживаться такой схемы, т.к. FixtureSetup от других тестов сможет кое-что подпортить. Потому создание контекста все же лучше делать в Setup методе.


ulu>Наоборот, наверное. FixtureSetup вызывается только один раз, а Setup -- перед каждым тестом.

И если тестов много и порядок их выполнения не определен, то перед выполнением Setup для конкретного теста может выполнитсья FixtureSetup чужого теста (В NUnit не силен, потому оперирую аналогиями ClassInitialize/ClassCleanup из vsts. Там вообще вызов ClassCleanup метода разве что гарантируется, но то что он будет вызыван сразу после всех тестов класса — не факт... Да и тесты одного класса могут быть перемешаны с тестами других классов в порядке выполнения), потому вызов Setup может вообще сломаться.

S>>З.Ы. Мы все же говорим о версии 3.3


ulu>В версии 3.3 не прокатит такая штука.

Угу. Но тема все же о версии 3.3
Re[16]: Rhino Mocks 3.3 Quick Reference
От: Ziaw Россия  
Дата: 01.12.08 14:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Там, кстати, нет никаких рекомендаций по поводу организации методов и тестов. Все AAA делается в одном методе. И это на самом деле удобнее чем Record-Playback.


Ну и слава богу Синтаксис действительно более говорящий.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[16]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 01.12.08 14:58
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, Aikin, Вы писали:


A>>Т.е. вот так:

Z>Да. Можно дейстивтельно сделать матрицу соответствий, если покажется, что она читабельнее:
Занятно. Мне больше нравится вариант с выделением хелпера и теста на кейс:

[Test]
public void Case1()
{
    AssertThatSomethingWorks(1, 2, 3, 4);
}
    
[Test]
public void Case2()
{
    AssertThatSomethingWorks(2, 3, 4, 5);
}

public void AssertThatSomethingWorks(int inParameter1, int inParameter1, int inParameter2, int inParameter3, int result)
{
    Assert.That(myOgject.MyMethod(c.a1, c.a2, c.a3), Is.EqualTo(c.result));
}

Либо использовать параметризированные тесты.


Z>>>Я не понимаю, как SRP может давать рекомендацию тестировать один класс (соответствующий SRP) несколькими тестами. Похоже на парадокс.

A>>Так, тест ([Test]) и набор тестов ([TestFixture]) это разные вещи.

Z>Ну да. В чем мой поинт: если тестируемый класс соотвествует SRP то и TestFixture в одном классе должен соотвествовать. А вот если тест превращается в ball of mud
Автор: ulu
Дата: 01.12.08
и нам требуется несколько классов для тестирования — проблема не решается разбиением тестов, мы только скроем симптомы.

Скорее всего да. Но ничего конкретнее сказать не могу.
Re[16]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 15:07
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, ulu, Вы писали:


Z>>>Итак, какие недостатки я вижу:


Z>>>...


ulu>>Я же говорю, кому-то подходит, кому-то нет..


Z> Где достоинства? Это религия что-ли?


Я уже запутался в ветках, но в какой-то из них я писал. Если кратко, такой стиль очень хорошо проясняет суть (но это субъективно, для кого-то он ее замутняет) -- ясно, где тут контекст, где тестируемое действие, и какой результат проверяем. С другой стороны, лично мне (и, как показывает опыт чтения группы Rhino Mocks, многим другим) гораздо менее очевиден синтаксис record-replay и отличие между stub и mock (это непонимание вызывает гигантское количество ошибок). Например, мы тут в блоке record записываем ожидания: это одновременно Arrange и Assert. Все это очень непохоже на обычный человеческий способ формулировать требования: в такой-то ситуации, если сделать то-то, будет такой-то результат.

А вообще, один ассерт в методе -- это не новая идея. Достаточно прогуглить "Single assert per test" или почитать здесь
Re[16]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 15:11
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, ulu, Вы писали:


ulu>>Здравствуйте, samius, Вы писали:


S>>>В случае тестирования с внешним состоянием (например БД), будет невозможно придерживаться такой схемы, т.к. FixtureSetup от других тестов сможет кое-что подпортить. Потому создание контекста все же лучше делать в Setup методе.


ulu>>Наоборот, наверное. FixtureSetup вызывается только один раз, а Setup -- перед каждым тестом.

S>И если тестов много и порядок их выполнения не определен, то перед выполнением Setup для конкретного теста может выполнитсья FixtureSetup чужого теста (В NUnit не силен, потому оперирую аналогиями ClassInitialize/ClassCleanup из vsts. Там вообще вызов ClassCleanup метода разве что гарантируется, но то что он будет вызыван сразу после всех тестов класса — не факт... Да и тесты одного класса могут быть перемешаны с тестами других классов в порядке выполнения), потому вызов Setup может вообще сломаться.

М-да, VSTS жжот. В mbUnit (и, насколько я понимаю, в *Unit) все-таки тестовые классы выполняются по очереди, вначале FixtureSetup, потом для каждого теста Setup.
Re[17]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 01.12.08 15:19
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, samius, Вы писали:


S>>И если тестов много и порядок их выполнения не определен, то перед выполнением Setup для конкретного теста может выполнитсья FixtureSetup чужого теста (В NUnit не силен, потому оперирую аналогиями ClassInitialize/ClassCleanup из vsts. Там вообще вызов ClassCleanup метода разве что гарантируется, но то что он будет вызыван сразу после всех тестов класса — не факт... Да и тесты одного класса могут быть перемешаны с тестами других классов в порядке выполнения), потому вызов Setup может вообще сломаться.


ulu>М-да, VSTS жжот. В mbUnit (и, насколько я понимаю, в *Unit) все-таки тестовые классы выполняются по очереди, вначале FixtureSetup, потом для каждого теста Setup.


А чем *Unit определяется порядок выполнения тестов? Только внутренними соображениями фреймворка?
Re[16]: Один класс - один тест
От: ulu http://sm-art.biz
Дата: 01.12.08 17:52
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, Aikin, Вы писали:


Z>>>Я не понимаю, как SRP может давать рекомендацию тестировать один класс (соответствующий SRP) несколькими тестами. Похоже на парадокс.

A>>Так, тест ([Test]) и набор тестов ([TestFixture]) это разные вещи.

Z>Ну да. В чем мой поинт: если тестируемый класс соотвествует SRP то и TestFixture в одном классе должен соотвествовать. А вот если тест превращается в ball of mud
Автор: ulu
Дата: 01.12.08
и нам требуется несколько классов для тестирования — проблема не решается разбиением тестов, мы только скроем симптомы.


Под ball of mud я понимаю большие классы с большими методами, которые занимаются много чем. А насчет один класс — один тест -- меня в свое время очень впечатлила вот эта статья.
Re[18]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 01.12.08 17:56
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, ulu, Вы писали:


ulu>>Здравствуйте, samius, Вы писали:


S>>>И если тестов много и порядок их выполнения не определен, то перед выполнением Setup для конкретного теста может выполнитсья FixtureSetup чужого теста (В NUnit не силен, потому оперирую аналогиями ClassInitialize/ClassCleanup из vsts. Там вообще вызов ClassCleanup метода разве что гарантируется, но то что он будет вызыван сразу после всех тестов класса — не факт... Да и тесты одного класса могут быть перемешаны с тестами других классов в порядке выполнения), потому вызов Setup может вообще сломаться.


ulu>>М-да, VSTS жжот. В mbUnit (и, насколько я понимаю, в *Unit) все-таки тестовые классы выполняются по очереди, вначале FixtureSetup, потом для каждого теста Setup.


S>А чем *Unit определяется порядок выполнения тестов? Только внутренними соображениями фреймворка?


Насколько я знаю, порядок исполнения тестовых методов внутри класса не определен. Но в mbUnit у аттрибута Test есть свойство Order, и есть аттрибут DependsOn.
Re[16]: Rhino Mocks 3.3 Quick Reference
От: C...R...a...S...H  
Дата: 10.12.08 20:51
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z> Где достоинства? Это религия что-ли?


Странно, что люди применяют технологии и техники даже не задумываясь, а зачем они нужны.
Техника, которую предлагают Aikin и ulu имеет очень интересный плюс.
А именно:
Пусть у вас есть тест:

TestX
{
  //init x,y etc
  assert.That(x.i,Is(y.i));
  assert.That(x.j,Is(y.j));
  assert.That(x.k,Is(y.k));
}


Пусть вы сделали рефакторинг и оказалось что все методы x(i,j,k) содержат ошибку.
После запуска теста, в увидите ошибку только в методе i
Когда вы ее исправите вы увидете что сломался следующий тест.
И т.д. и т.п.

TestXi
{
  assert.That(x.k,Is(y.k));
}
TestXj
{
  assert.That(x.k,Is(y.k));
}
TestXk
{
  assert.That(x.k,Is(y.k));
}

А вот перераспределение assert позволит вам сразу определить, что у вас падают все методы и проблема может скрываться в общим для них функционале или на оборот.
На лицо экономия времени, а значит и $$$

Сам я с такой техникой еще не работал, и меня очень интересует, как Aikin и ulu будут тестировать такой класс

class Entity
{
 string Name;
 dateTime date;
 ... 
}
class XDAO
{
  Create();
  Entity Read(...);
  Update(...);
  Delete(...);
}


Ведь для кейса Update необходимо проверить обновились ли все поля у Entity, а полей может быть 10,20,30,40 и 40 раз ходить в базу я думаю не прикольно
Там было написано русским по белому...
Re[17]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 10.12.08 22:07
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>Здравствуйте, Ziaw, Вы писали:


Z>> Где достоинства? Это религия что-ли?


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

CRA>Техника, которую предлагают Aikin и ulu имеет очень интересный плюс.
CRA>А именно:
CRA>Пусть у вас есть тест:

CRA>
CRA>TestX
CRA>{
CRA>  //init x,y etc
CRA>  assert.That(x.i,Is(y.i));
CRA>  assert.That(x.j,Is(y.j));
CRA>  assert.That(x.k,Is(y.k));
CRA>}
CRA>


CRA>Пусть вы сделали рефакторинг и оказалось что все методы x(i,j,k) содержат ошибку.

CRA>После запуска теста, в увидите ошибку только в методе i
CRA>Когда вы ее исправите вы увидете что сломался следующий тест.
CRA>И т.д. и т.п.

CRA>
CRA>TestXi
CRA>{
CRA>  assert.That(x.k,Is(y.k));
CRA>}
CRA>TestXj
CRA>{
CRA>  assert.That(x.k,Is(y.k));
CRA>}
CRA>TestXk
CRA>{
CRA>  assert.That(x.k,Is(y.k));
CRA>}

CRA>

CRA>А вот перераспределение assert позволит вам сразу определить, что у вас падают все методы и проблема может скрываться в общим для них функционале или на оборот.
CRA>На лицо экономия времени, а значит и $$$

CRA>Сам я с такой техникой еще не работал, и меня очень интересует, как Aikin и ulu будут тестировать такой класс


CRA>
CRA>class Entity
CRA>{
CRA> string Name;
CRA> dateTime date;
CRA> ... 
CRA>}
CRA>class XDAO
CRA>{
CRA>  Create();
CRA>  Entity Read(...);
CRA>  Update(...);
CRA>  Delete(...);
CRA>}
CRA>


CRA>Ведь для кейса Update необходимо проверить обновились ли все поля у Entity, а полей может быть 10,20,30,40 и 40 раз ходить в базу я думаю не прикольно


Ходить в базу надо в FixtureSetup, а в Test проверять каждое поле.

Общее правило: в Test сидит только Assert -- то есть, никаких активных действий (Arrange, Act), только проверка.

Вообще-то соображения производительности (например, оптимизация запросов к базе) очень часто конфликтуют с соображениями гибкости ("агильности"). В данном случае еще повезло, что они хорошо согласуются.
Re[18]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.12.08 22:27
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, C...R...a...S...H, Вы писали:


ulu>Общее правило: в Test сидит только Assert -- то есть, никаких активных действий (Arrange, Act), только проверка.


А что если в одном тесте нам нужен Mock, а в другом — Stub? Т.е. один тест проверяет факт обращения к некоторому сервису, другой — проверяет корректность использования результата, возвращенного сервисом... Такие тесты должны быть в разных Fixture-ах по этим соображениям?

ulu>Вообще-то соображения производительности (например, оптимизация запросов к базе) очень часто конфликтуют с соображениями гибкости ("агильности"). В данном случае еще повезло, что они хорошо согласуются.


В общем идея понятна... Но при работе с vsts есть некоторые тонкости:
Во первых время вызова [ClassCleanup] метода (соответствует [TestFixtureTearDown]) не определено, т.к. тесты в vsts могут быть отсортированы по разным признакам, а так же методы [ClassInitialize] и [ClassCleanup] могут быть вызваны более одного раза за прогон тестов. Это значит, что мы не можем проинициализировать БД в [ClassInitialize] и очистить ее в [ClassCleanup], потому как между вызовами этих методов могут легко попасть другие тесты БД, которые попортят БД...
Во вторых — время жизни класса с тестами (Fixture) в vsts определено одним тестом. Это значит, что в полях экземпляра класса невозможно сохранить состояния для тестов (чтобы пощупать его в Assert).
Таким образом выходит, что нужно либо мудрить со статическими переменными класса, либо Arrange, Act и Assert делать в одном методе, либо в [TestInitialize/TestCleanup] (соответственно Setup/TearDown)

Есть какие-нибудь соображения по поводу vsts?
Re[19]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 10.12.08 22:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, ulu, Вы писали:


ulu>>Здравствуйте, C...R...a...S...H, Вы писали:


ulu>>Общее правило: в Test сидит только Assert -- то есть, никаких активных действий (Arrange, Act), только проверка.


S>А что если в одном тесте нам нужен Mock, а в другом — Stub? Т.е. один тест проверяет факт обращения к некоторому сервису, другой — проверяет корректность использования результата, возвращенного сервисом... Такие тесты должны быть в разных Fixture-ах по этим соображениям?


К счастью, любимые мной Rhino Mocks и TypeMock перешли на новый синтаксис как раз с целью поддержки AAA. Теперь не модно делить с самого начала на мок и стаб. Теперь ты вначале объявляешь, что оно у нас мок, а в тесте используешь что-то типа AssertWasCalled(x=>x.MyMethod()) (если нужно проверить факт обращения).

ulu>>Вообще-то соображения производительности (например, оптимизация запросов к базе) очень часто конфликтуют с соображениями гибкости ("агильности"). В данном случае еще повезло, что они хорошо согласуются.


S>В общем идея понятна... Но при работе с vsts есть некоторые тонкости:

S>Во первых время вызова [ClassCleanup] метода (соответствует [TestFixtureTearDown]) не определено, т.к. тесты в vsts могут быть отсортированы по разным признакам, а так же методы [ClassInitialize] и [ClassCleanup] могут быть вызваны более одного раза за прогон тестов. Это значит, что мы не можем проинициализировать БД в [ClassInitialize] и очистить ее в [ClassCleanup], потому как между вызовами этих методов могут легко попасть другие тесты БД, которые попортят БД...
S>Во вторых — время жизни класса с тестами (Fixture) в vsts определено одним тестом. Это значит, что в полях экземпляра класса невозможно сохранить состояния для тестов (чтобы пощупать его в Assert).
S>Таким образом выходит, что нужно либо мудрить со статическими переменными класса, либо Arrange, Act и Assert делать в одном методе, либо в [TestInitialize/TestCleanup] (соответственно Setup/TearDown)

S>Есть какие-нибудь соображения по поводу vsts?


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

Вообще, похоже, что vsts создавался для QA и тестирования после написания кода. Для TDD, наверное, им не стоит пользоваться.
Re[20]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.12.08 22:57
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, ulu, Вы писали:


ulu>>>Здравствуйте, C...R...a...S...H, Вы писали:


ulu>>>Общее правило: в Test сидит только Assert -- то есть, никаких активных действий (Arrange, Act), только проверка.


S>>А что если в одном тесте нам нужен Mock, а в другом — Stub? Т.е. один тест проверяет факт обращения к некоторому сервису, другой — проверяет корректность использования результата, возвращенного сервисом... Такие тесты должны быть в разных Fixture-ах по этим соображениям?


ulu>К счастью, любимые мной Rhino Mocks и TypeMock перешли на новый синтаксис как раз с целью поддержки AAA. Теперь не модно делить с самого начала на мок и стаб. Теперь ты вначале объявляешь, что оно у нас мок, а в тесте используешь что-то типа AssertWasCalled(x=>x.MyMethod()) (если нужно проверить факт обращения).

Да, причем можно и к Stub-ам так обращаться. Но это небольшое дублирование. Сначала нужно указать, что вернуть на вызов метода, потом спросить а был ли он вызван. Но беда не в этом, а в том, что негде хранить результат для Assert-а в случае с vsts.

ulu>>>Вообще-то соображения производительности (например, оптимизация запросов к базе) очень часто конфликтуют с соображениями гибкости ("агильности"). В данном случае еще повезло, что они хорошо согласуются.


S>>Есть какие-нибудь соображения по поводу vsts?


ulu>Мм.. похоже, что соображение одно -- перейти на что-нибудь другое Если серьезно, то я практически никогда этим не пользовался.

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

ulu>Вообще, похоже, что vsts создавался для QA и тестирования после написания кода. Для TDD, наверное, им не стоит пользоваться.

Да хоть до, хоть после, все равно он какой-то не такой... Купились в 2005-ом году еще на то, что он интегрирован в студию. На странности стали обращать внимание уже тогда, когда было написано довольно много. Допекло это когда уже переходить было поздновато.
Кроме перечисленных мной неудобств там есть еще куча, которые тоже в общем-то не сразу обнаруживаются. Такие как игнорирование тестов, определенных в базовом классе; игнорирование методов [ClassInitialize] в базовом классе Fixture, если базовый класс определен в другой сборке; неустойчивость работы TestHost-а, который черезвычайно легко вышибить и т.п.
Re[17]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 11.12.08 07:43
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>Сам я с такой техникой еще не работал, и меня очень интересует, как Aikin и ulu будут тестировать такой класс

CRA>Ведь для кейса Update необходимо проверить обновились ли все поля у Entity, а полей может быть 10,20,30,40 и 40 раз ходить в базу я думаю не прикольно
Начну я с того, что этот тест никак не претендует на utit-тест, так как общается с базой (еще вопрос изменит ли что-то факт использования in-memory DB). Поэтому он будет выполняться на CI сервере для которого время выполнения играет не такую важную роль, как для программиста выполняющего тесты "вручную".

Далее. Для проверки сущностей на полное соответствие я создм хелпер: EntityHelper.AssertEqual(entity, expectedEntity). Ведь в данном случае не важны значения элеменов сущности по отдельности, так как в базу они идут всем скопом, забираются тоже. И если что-то поломалось, то 90% что поломался весь механизм, а не "сэйвер/геттер/сеттер" конкретного поля (кста, "сэйвер/геттер/сеттер" также указывает на то, что тест у нас интеграционный, а не юнит).

Если же кровь из носу хочется протестировать поля по отдельности, то лучшим вариантом будет подход ulu с выделением "хождения в базу" в FixtureSetup. Хоть он мне и не нравится

СУВ, Aikin
Re[18]: Rhino Mocks 3.3 Quick Reference
От: C...R...a...S...H  
Дата: 11.12.08 07:55
Оценка:
Здравствуйте, Aikin, Вы писали:

CRA>>Сам я с такой техникой еще не работал, и меня очень интересует, как Aikin и ulu будут тестировать такой класс

CRA>>Ведь для кейса Update необходимо проверить обновились ли все поля у Entity, а полей может быть 10,20,30,40 и 40 раз ходить в базу я думаю не прикольно
A>Начну я с того, что этот тест никак не претендует на utit-тест, так как общается с базой (еще вопрос изменит ли что-то факт использования in-memory DB). Поэтому он будет выполняться на CI сервере для которого время выполнения играет не такую важную роль, как для программиста выполняющего тесты "вручную".
Назовите их интеграционными, да хоть fit-test только проблема не решается.


A>Далее. Для проверки сущностей на полное соответствие я создм хелпер: EntityHelper.AssertEqual(entity, expectedEntity). Ведь в данном случае не важны значения элеменов сущности по отдельности, так как в базу они идут всем скопом, забираются тоже. И если что-то поломалось, то 90% что поломался весь механизм, а не "сэйвер/геттер/сеттер" конкретного поля (кста, "сэйвер/геттер/сеттер" также указывает на то, что тест у нас интеграционный, а не юнит).

Ну то, что поломался весь механизм, это вы загнули.


A>Если же кровь из носу хочется протестировать поля по отдельности, то лучшим вариантом будет подход ulu с выделением "хождения в базу" в FixtureSetup. Хоть он мне и не нравится

И сколько дней такой тест будет проходить???
Там было написано русским по белому...
Re[19]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 11.12.08 08:19
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>>>Сам я с такой техникой еще не работал, и меня очень интересует, как Aikin и ulu будут тестировать такой класс

CRA>>>Ведь для кейса Update необходимо проверить обновились ли все поля у Entity, а полей может быть 10,20,30,40 и 40 раз ходить в базу я думаю не прикольно
A>>Начну я с того, что этот тест никак не претендует на utit-тест, так как общается с базой (еще вопрос изменит ли что-то факт использования in-memory DB). Поэтому он будет выполняться на CI сервере для которого время выполнения играет не такую важную роль, как для программиста выполняющего тесты "вручную".
CRA>Назовите их интеграционными, да хоть fit-test только проблема не решается.
А в чем проблема? В скорости выполнения?
Так ведь от "названия" теста очень сильно зависят приемлемое время выполнения. Если для юнит-тестов это время ~0,1 сек то для интеграционных 1-2 сек вполне нормальное время.

A>>Далее. Для проверки сущностей на полное соответствие я создм хелпер: EntityHelper.AssertEqual(entity, expectedEntity). Ведь в данном случае не важны значения элеменов сущности по отдельности, так как в базу они идут всем скопом, забираются тоже. И если что-то поломалось, то 90% что поломался весь механизм, а не "сэйвер/геттер/сеттер" конкретного поля (кста, "сэйвер/геттер/сеттер" также указывает на то, что тест у нас интеграционный, а не юнит).

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

A>>Если же кровь из носу хочется протестировать поля по отдельности, то лучшим вариантом будет подход ulu с выделением "хождения в базу" в FixtureSetup. Хоть он мне и не нравится

CRA>И сколько дней такой тест будет проходить???
Столько же сколько и обычный.

Обычный:
[TestFixture]
public class EntityDaoTests()
{
    public void UpdateEntityTest()
    {
        // загрузили
        // изменили
        // сохранили
        
        // загрузили из базы
        // проверили все поля по очереди
    }
}

Предложенный ulu:

[TestFixture]
public class UpdateEntityDaoTests()
{
  private Entity _expected;
  private Entity _fromDB;
    [SetUpFixture]
    public void FixtureSetup()
    {
        // загрузили
        // изменили
        // сохранили
        _expected = changedEntity;
                
        // загрузили из базы
        _fromDB = entityFromDB;
    }
    
    public void Field1Test()
    {
        Assert.That(_fromDB.Field1, Is.EqualTo(_expected.Field1);
    }
    public void Field2Test()
    {
        Assert.That(_fromDB.Field2, Is.EqualTo(_expected.Field2);
    }
}
Re[20]: Rhino Mocks 3.3 Quick Reference
От: C...R...a...S...H  
Дата: 11.12.08 08:26
Оценка:
Здравствуйте, Aikin, Вы писали:


A>Предложенный ulu:


A>
A>[TestFixture]
A>public class UpdateEntityDaoTests()
A>{
A>  private Entity _expected;
A>  private Entity _fromDB;
A>    [SetUpFixture]
A>    public void FixtureSetup()
A>    {
A>        // загрузили
A>        // изменили
A>        // сохранили
A>        _expected = changedEntity;
                
A>        // загрузили из базы
A>        _fromDB = entityFromDB;
A>    }
    
A>    public void Field1Test()
A>    {
A>        Assert.That(_fromDB.Field1, Is.EqualTo(_expected.Field1);
A>    }
A>    public void Field2Test()
A>    {
A>        Assert.That(_fromDB.Field2, Is.EqualTo(_expected.Field2);
A>    }
A>}
A>

Спасибо. Разобрался.
Попробую поиспользовать.
Есть еще один вопрос. Вас не запаривает писать столько тестов. Ведь их количество растет по прогрессии
Там было написано русским по белому...
Re[21]: Rhino Mocks 3.3 Quick Reference
От: Aikin Беларусь kavaleu.ru
Дата: 11.12.08 08:47
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>Спасибо. Разобрался.

Не за что.

CRA>Попробую поиспользовать.

Как я говорил, мне этот подход не совсем нравится

CRA>Есть еще один вопрос. Вас не запаривает писать столько тестов. Ведь их количество растет по прогрессии

Нет тут никакой прогрессии. Если изолировать тестируемый класс от зависимостей, то никакого комбинаторного взрыва не будет.

Интеграционные же тесты должны писаться QA отделом (у меня такого нет ). Меня интересует не сломал ли я что-то в текущей правке, что в 99% покрывается юнит тестами. Остальной 1% тестируется вручную либо нами, но чаще на стороне заказчика (он у нас не злой, мы ему вообще систему из руин подняли ). Можно прикрутить FIT-тесты но как-то все руки не доходят

СУВ, Aikin
Re[18]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 11.12.08 10:20
Оценка:
A>Далее. Для проверки сущностей на полное соответствие я создм хелпер: EntityHelper.AssertEqual(entity, expectedEntity). Ведь в данном случае не важны значения элеменов сущности по отдельности, так как в базу они идут всем скопом, забираются тоже. И если что-то поломалось, то 90% что поломался весь механизм, а не "сэйвер/геттер/сеттер" конкретного поля (кста, "сэйвер/геттер/сеттер" также указывает на то, что тест у нас интеграционный, а не юнит).

Да, этот подход мне больше нравится, чем мой.
Re[21]: Rhino Mocks 3.3 Quick Reference
От: ulu http://sm-art.biz
Дата: 11.12.08 10:22
Оценка:
Здравствуйте, samius, Вы писали:
ulu>>Мм.. похоже, что соображение одно -- перейти на что-нибудь другое Если серьезно, то я практически никогда этим не пользовался.
S>Перейти в текущем проекте практически нереально, слишком много придется переделывать. Придется жевать кактус до конца.

Может, просто Find/Replace TestMethod на Test и т.д.? Или оставить старые тесты в vsts, а новые писать на *Unit?
Re[22]: Rhino Mocks 3.3 Quick Reference
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.12.08 10:30
Оценка:
Здравствуйте, ulu, Вы писали:

ulu>Здравствуйте, samius, Вы писали:

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

ulu>Может, просто Find/Replace TestMethod на Test и т.д.? Или оставить старые тесты в vsts, а новые писать на *Unit?

Имеет смысл оценить на одном из проектов сложность перехода. Наверняка большинство тестов задышут. Однако, к сожалению, решать вопрос о переходе буду не я. Негативным моментом будет то, что придется осваивать новые тулзы (сам *Unit, NCover, NCoverExplorer...), начальству это не понравится.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.