Модульные тесты — рефакторинг для обмена данными между тестами на C#

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

public class BaseClassValidator {
   [Test]
   public void TestAddress(){
     Address a = GetAddress();
     if (a != null){
        // verify and validate here
        Assert.AreEqual(..., ...);
     }
   }

   [Test]
   public void TestPhone(){
       // almost the same as above, with GetPhone();
   }

   // ... other public methods here ...

   protected Address GetAddress(){
     return null;
   }

   protected Phone GetPhone(){
     return null;
   }
}

public class US: BaseClassValidator{
    protected override Address GetAddress(){
       Address address = new Address();
       address.FirstName = "firstname";
       // fill in the address data ...
       return address;           
    }

    // override GetPhone as well and other protected methods
}

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

public class US: BaseClassValidator {

    // override the method GetAddress, as explained above ...

    // define a new test method here...
    [Test]
    public void TestValidator {
        Address a = GetAddress();
        a.State = "KS";
        // validate the address
        // and assert that we get an error because state is wrong

        Address a = GetAddress();
        a.street = "";
        // validate and assert that we get an error because street is wrong


        // and so on...
    }

}

Мне было интересно, есть ли лучший способ сделать это, так как кажется, что мы частично используем базовый класс для проверки некоторых данных, но для чего-то более конкретного мы используем подклассы - это может иметь смысл, но тогда кажется мы теряем преимущество использования шаблона, как показано выше. Что мне не нравится, так это способ создания данных, потому что при другом подходе, например, при использовании тестов, управляемых данными, мы могли бы читать тестовые данные из файла (например, xml).

Есть ли лучший способ обмена данными между тестами? Как вы справляетесь с такого рода ситуациями?


person Markon    schedule 20.11.2014    source источник


Ответы (2)


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

Люди склонны использовать композицию вместо наследования, поэтому использование подклассов — не лучшее решение для модульного тестирования. .

Вы пробовали Object Mother или Шаблоны Test Data Builder? Их можно использовать для простого создания данных для ваших тестов.

Существуют примеры использования Test Data Builder.

var defaultAddres = new AddressBuilder().Build();
var addresWithState = new AddressBuilder().WithState("MyState").Build();
var addresWithStreet2 = new AddressBuilder().WithStreet2("street 2 value").Build();

и его простая реализация

public class AddressBuilder
{
    string state = "default STATE";
    string street1 = "default street 1";
    string street2 = "";

    public Address Build()
    {
        return new Address
        {
            State = state,
            Street1 = street1,
            Street2 = street2
        };
    }

    public AddressBuilder WithState(string value)
    {
        state = value;
        return this;
    }

    public AddressBuilder WithStreet1(string value)
    {
        street1 = value;
        return this;
    }

    public AddressBuilder WithStreet2(string value)
    {
        street2 = value;
        return this;
    }
}
person Ilya Palkin    schedule 25.11.2014

В настоящее время я работаю над чем-то подобным и ввел в свой проект класс Data. Это просто содержит кучу статических данных. Это частичный класс, поэтому я могу его немного структурировать. У меня есть DataOrder.cs, DataOrderLine.cs и так далее. Затем есть общедоступное свойство, например Orders, которое я могу использовать в своем тесте для получения тестовых данных.

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

person Gerrie Schenck    schedule 20.11.2014
comment
А что вы делаете в конкретных случаях, например, мне нужен адрес, но я должен изменить только одно поле, например, улицу? - person Markon; 20.11.2014
comment
Если вам нужны конкретные данные, вы все равно можете создать их в своем тесте. Если это нужно нескольким тестам, переместите его в классы данных. - person Gerrie Schenck; 20.11.2014