2010-01-07 7 views
0

в текущей версии NUnit, я могу параметризовать TestFixture и создать ее несколько раз. Например:Преобразуйте строку в код C#

[TestFixture("var1")] 
[TestFixture("var2")] 
[TestFixture("var3")] 
public class MyTestFixture 
{ 
    private string var; 

    public MyTestFixture(string var) 
    { 
     this.var = var; 
    } 

    ... 

} 

Это будет создавать экземпляр MyTestFixture 3 раза с параметром аргумента. Моя проблема в том, что текущий NUnit не имеет функции источника данных для атрибута TextFixture (только TestCaseSource). Мне нужно создать экземпляр TestFixture на основе ввода данных, и каждый TestFixture имеет разные наборы данных тестовых данных. Без проблем с данными тестового случая, благодаря TestCaseSource. Но как я могу это сделать для атрибута TestFixture?

Моя идея заключается в том, чтобы создать атрибут TestFixture на лету затем изменить его на строки кода и вставить в тестовый код и т.д .: что-то вроде этого:

ConvertToCode(GenerateTestFixture()); 
public class MyTestFixture 
{ 
    ... 
} 

Как я могу это сделать? Или есть лучший способ?

Большое спасибо за помощь.

С наилучшими пожеланиями,
Эдвард

ответ

3

Создание атрибутов для вашего метода на лету возможно, но трудно. Вам лучше найти другой подход.

Атрибуты (например, [TestFixture]), которые вы получили, считываются компилятором, когда ваш код скомпилирован и автоматически вставлен в ваш код.

Чтобы создать свои собственные атрибуты для классов, вам нужно использовать что-то вроде Reflection.Emit, чтобы изменить сгенерированные сборки как шаг после сборки для проекта. Это похоже на то, как писать язык ассемблера напрямую (вы создаете MSIL), который может быть интересным, но нелегким и сделает ваш код очень сложным для обслуживания!

Альтернативный подход может иметь перечисление контролировать тестовые случаи, и есть метод, который проверяет перечисление и возвращает соответствующие данные:

public enum TestController 
{ 
    Value1, 
    Value2, 
    Value3 
} 

[TestFixture(TestController.Value1)] 
[TestFixture(TestController.Value2)] 
[TestFixture(TestController.Value3)] 
public class MyTestFixture 
{ 
    public MyTestFixture(TestController testController) 
    { 
     var dataForTest = GetDataForTest(testController); 
    } 

    ... 

} 

Метод GetDataForTest() бы тогда какой-то переключатель заявление для генерации данных.

Альтернативным подходом может быть использование типа, а не перечисление, а затем экземпляр типа в методе GetDataForTest() и вызов фабричного метода - но я думаю, что это может быть немного сложнее.

+0

Большое спасибо Джереми. Дело в том, что TestFixture управляется данными, поэтому я не знаю заранее, сколько будет стоить. Будет ли другой подход работать для данных TestFixture? Если да, не могли бы вы дать мне короткий образец? Снова благодарим вас за помощь. С уважением, Edward – 2010-01-07 10:33:24

+0

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

+0

На самом деле тест уже существует с одним тестовым случаем, проверяющим все элементы данных, у нас также есть собственный результат теста для генерации результата для каждого элемента данных. Но поскольку NUnit 2.5 поддерживает управление данными, мне было поручено преобразовать существующий тест с данными UNIT. Это имеет некоторые преимущества по сравнению с существующим тестом, например, лучше выглядеть в пользовательском интерфейсе, может запускать один тест и т. Д. Я могу просто использовать TestCaseSource, проблема в том, что тестовое имя становится очень длинным с большим количеством дубликатов в качестве тестовых примеров иерархическая. Я думаю, что попробую Reflection.Emit попробовать. Большое спасибо за Вашу помощь. С уважением, Edward – 2010-01-07 13:14:10

0

Это стало возможным в NUnit 3.x, используя атрибут TestFixtureSource. Создайте класс, который реализует IEnumerable с вашими ценностями затем использовать его следующим образом:

[TestFixtureSource(typeof(Foo), Category = "Quux")] 
public class BarTest 
{  
    public BarTest(object baz) 
    { 
     _baz = baz; 
    { 
} 

Единственное, что изменилось с TestCaseSource и относится к TestFixtureSource является то, что вы должны либо дать ему тип, который реализует IEnumerable или дать ему статический метод.Если вы полагались на свойства или методы, которые генерируют данные из конструктора, вам нужно либо реорганизовать статическим способом, либо просто реализовать класс IEnumerable и передать себя как тип источника.

 Смежные вопросы

  • Нет связанных вопросов^_^