Должен ли я проверить, что определенная тестируемая система реализует IFoo, IBar и MyBaseClass? - PullRequest
2 голосов
/ 04 мая 2011

У меня есть случай, когда конструктор моего базового класса выдает исключения при предоставлении неверных аргументов.
Поскольку я не хочу копировать / вставлять один и тот же тест снова и снова, я хотел бы убедиться, что система подtest фактически реализует IFoo, IBar и MyBaseClass.
С одной стороны, имеет смысл, что мой класс будет реализовывать IFoo, IBar и MyBaseClass, но с другой стороны, если моя реализация изменится, у меня будет еще один тест для поддержки, и если я 'Я сделаю из этого соглашение, при перестройке иерархии наследования могут возникнуть некоторые издержки.

Ответы [ 3 ]

2 голосов
/ 05 мая 2011

Как правило, я предпочитаю тестировать поведение, а не реализацию.Например, я хотел бы убедиться, что мой SUT может делать , что предлагают IFoo и IBar.С точки зрения бизнеса не имеет значения, реализует ли MyClass IFoo или нет.Что важно , так это то, что objectUnderTest реализует DoThis ().

Assaf.

1 голос
/ 05 мая 2011

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

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

Я только что сделал нечто подобное, чтобы протестировать метод, который для многих реализаций является операцией без операции (он просто возвращает то, что ему было дано), но для некоторых реализаций он что-то делает, и поэтому тесты кода операции не выполняются. единый базовый класс с абстрактным методом для получения объекта для тестирования (получает экземпляр интерфейса, в котором живет метод no op), и конкретные реализации, которые должны быть просто no op, расширяют этот класс и переопределяют абстрактный метод для возврата экземпляр класса, на котором мы хотим протестировать методы.

это помогло мне решить мою проблему, надеюсь, это поможет и вам.

public abstract class BaseClass
{
    public abstract void CallConstructor(SomeType arg1, SomeType2 arg2);

    [Test]
    public void Constructor_WhenArg1IsNull_ArgumentNullExceptionIsThrown()
    {
        Assert.Throws<ArgumentNullException>(()=>CallConstructor(null, new SomeType2()));       
    }

    [Test]
    public void Constructor_WhenArg2IsNull_ArgumentNullExceptionIsThrown()
    {
        Assert.Throws<ArgumentNullException>(()=>CallConstructor(new SomeType(), null));       
    }
}

[TestFixture]
public class ConcreteImplementation1Tests : BaseClass
{
    public override void CallConstructor(SomeType arg1, SomeType2 arg2)
    {
    new ConcreteImplementation1(arg1,arg2);
    }
}

[TestFixture]
public class ConcreteImplementation2Tests : BaseClass
{
    public override void CallConstructor(SomeType arg1, SomeType2 arg2)
    {
    new ConcreteImplementation2(arg1,arg2);
    }
}

в дополнение к этому та же самая техника может использоваться для тестирования общего

функциональность для всех классов, которые реализуют интерфейс. Используя IList в качестве примера:

public abstract class ListImplementationsCommonTests
{
    public abstract IList GetListImplementation();

    [Test]
    public void Add_WhenValidItemIsAdded_ItCanBeFound()
    {
        IList list = GetListImplementation();
        object item = new Object();
        list.Add(item);
        Assert.That(list.Contains(item));      
    }

    [Test]
    public void Add_WhenNullIsAdded_ArgumentNullExceptionIsThrown()
    {
        IList list = GetListImplementation();
        Assert.Throws<ArgumentNullException>(()=>list.Add(null));              
    }

    ...
    //more common tests
    ...
}

Затем каждая реализация IList (например, ArrayList, LinkedList, DoubleLinkedList, SortedList и т. Д.) Может быть затем протестирована с одним и тем же кодом без необходимости повторять одни и те же тесты снова и снова:

[TestFixture]
public class ArrayListTests: ListImplementationCommonTests
{
    public override IList GetListImplementation()
    {
    return new ArrayList();
    }

   ...
   //Extra specific tests for the ArrayList

}

[TestFixture]
public class LinkedListTests: ListImplementationCommonTests
{
    public override IList GetListImplementation()
    {
    return new LinkedList();
    }

   ...
   //Extra specific tests for the LinkedList

}

[TestFixture]
public class SortedListTests: ListImplementationCommonTests
{
    public override IList GetListImplementation()
    {
    return new SortedList();
    }

   ...
   //Extra specific tests for the SortedList
}
0 голосов
/ 05 мая 2011

Тестируйте реализации IFoo и IBar отдельно от класса, который их реализует.Поэтому вам не нужно тестировать его, когда вы тестируете реализующий класс.

Для MyBaseClass (если он объявлен как MustInherit) я бы создал тестовый макет (который наследуется от MyBaseClass и находится в тестепроект) и протестируйте все, что сделано в MyBaseClass.

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