Коли я використовую атрибут TestFixtureSetUp замість конструктора за замовчуванням?


75

Документація NUnit не говорить мені, коли використовувати метод з a, TestFixtureSetupа коли робити налаштування в конструкторі.

public class MyTest
{
    private MyClass myClass;

    public MyTest()
    {
        myClass = new MyClass();
    }

    [TestFixtureSetUp]
    public void Init()
    {
        myClass = new MyClass();
    }
}

Чи є якісь хороші / погані практики щодо TestFixtureSetupконструктора за замовчуванням чи немає різниці?


Оскільки це питання часто задається, розгляньте це і це (ті самі обговорення MSTest). Але остерігайтеся побічних ефектів установок приладів на читабельність тесту (дивіться тут і тут ).
Massood Khaari

Тільки мій 1 цент: Це корисно, коли є базовий клас для багатьох тестів. Похідні класи автоматично запускатимуть TestFixtureSetup, визначений у батьківському класі. Ви не можете цього робити з конструкторами, якщо не зателефонуєте їм спеціально (це може бути проблемою, а може не бути, залежно від того, скільки похідних класів у вас є)
Нельсон Родрігес,

Відповіді:


18

Я думаю, що це була одна з проблем, яка не вирішувалась командою nUnit. Однак є чудовий проект xUnit, який побачив саме цю проблему і вирішив, що конструктори - це добре, що потрібно використовувати для ініціалізації тестового кріплення .

Для NUnit, моя найкраща практика в даному випадку було використовувати TestFixtureSetUp, TestFixtureTearDown, SetUpі TearDownметоди , як описано в документації.

Я думаю, що це також допомагає мені, коли я не думаю про тестовий пристрій nUnit як про звичайний клас, навіть якщо ви визначаєте його за допомогою цієї конструкції. Я вважаю їх пристосуваннями, і це мене переборює з розумовою перешкодою і дозволяє пропустити це питання.


2
Будь ласка , зверніть увагу , що стаття XUnit передбачає , що Setups (а також конструктори) , як правило , погана ідея , що робить код перевірки важко слідувати , що не то, що конструктори краще , ніж Setupс. Проте безпараметричні конструктори - це остання інстанція для тих, хто цього дійсно потребує. Також дивіться це: Тестуйте стилі та уникайте налаштування /
розірвання

64

Навіщо вам потрібно використовувати конструктор у своїх тестових класах?

Я використовую [SetUp]і [TearDown]позначені методи для коду, що виконується до і після кожного тесту, і, аналогічно, [TestFixtureSetUp]і [TestFixtureTearDown]позначені методи для коду, який виконується лише один раз до і після того, як всі тести в приладі були запущені.

Думаю, ви могли б, можливо, замінити [TestFixtureSetUp]конструктор (хоча я не пробував), але, здається, це лише відхиляється від чіткої домовленості, яку забезпечують позначені методи.


4
Я поняття не мав, навіщо мені конструктор, але також не маю уявлення, навіщо мені TestFixtureSetUp. Я знаю про атрибути setup, teardown і testfixtureteardown. Я просто не знаю різниці між конструктором та атрибутом testfixturesetup.
Пако

4
Просто щоб відповісти на ваше запитання. Вам потрібно використовувати конструктор у своїх тестових класах, якщо у вас є параметризовані тестові елементи.
oderibas

13

Одне, з чим ви не можете зробити [TestFixtureSetup]те, що ви можете зробити в конструкторі, - це отримання параметрів з [TestFixture].

Якщо ви хочете параметризувати свій тестовий прилад, тоді вам доведеться використовувати конструктор принаймні для деякої частини налаштування. Наразі я використовував це лише для тестів інтеграції, наприклад, для тестування рівня доступу до даних у кількох постачальників даних:

[TestFixture("System.Data.SqlClient",
  "Server=(local)\\SQLEXPRESS;Initial Catalog=MyTestDatabase;Integrated Security=True;Pooling=False"))]
[TestFixture("System.Data.SQLite", "Data Source=MyTestDatabase.s3db")])]
internal class MyDataAccessLayerIntegrationTests
{
    MyDataAccessLayerIntegrationTests(
        string dataProvider,
        string connectionString)
    {
        ...
    }
}

10

Існує різниця між конструктором та методом, позначеним [TestFixtureSetUp]атрибутом. Відповідно до документації NUnit:

Бажано, щоб конструктор не мав жодних побічних ефектів, оскільки NUnit може побудувати об'єкт кілька разів протягом сеансу.

Тож якщо у вас є якась дорога ініціалізація, краще скористатися TestFixtureSetUp.


1
Це передбачає, що метод, позначений TestFixtureSetUp, є статичним. В іншому випадку неможливо було б, щоб конструктор викликався частіше, якщо тестовий екземпляр не буде викинутий без використання NUnit, що я б сумнівався.
jpierson

9

Я часто задавався питанням, у чому була потреба [TestFixtureSetUp], враховуючи те, що існує проста, добре зрозуміла конструкція першокласного мови, яка робить точно те саме.

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


4
Ключове слово readonly не гарантує, що учасник не буде модифікований. Якщо учасником є ​​клас, внутрішній стан класу можна змінити в тесті, і цей стан буде перенесено до наступного методу тестування (оскільки nunit не відтворює клас між кожним тестовим запуском)
Піт,

4

[TestFixtureSetUp]і [TestFixtureTearDown]призначені для цілого тестового класу. працює лише один раз.

[SetUp]і [TearDown]призначені для кожного методу випробування (тесту). працює для кожного тесту.


3

Важливою відмінністю конструктора від TestFixtureSetUp є те, що принаймні в NUnit 2 код конструктора фактично виконується під час перелічення тесту, а не лише тестового запуску, тому в основному ви хочете обмежити код ctor лише заповненням читання, тобто параметром, значеннями. Все, що спричиняє побічні ефекти або робить будь-яку реальну роботу, потрібно або загортати в Ледачий, або робити в TestFixtureSetUp / OneTimeSetUp. Отже, ви можете вважати конструктор виключно місцем для налаштування тесту. Тоді як TestFixtureSetUp - це місце, де тестовий прилад, необхідний початковий стан системи перед запуском тестів, ініціалізується.


це хороший момент, не впевнений, наскільки актуальним сьогодні, але що слід врахувати.
Айодінцов,

2

Я думаю, що у мене є негативна хороша відповідь - причина використовувати конструктор замість атрибута - це коли у вас є спадщина між тестовими класами.

[TestFixtureSetup]Буде викликаний лише один метод, котрий коментується , (лише для конкретного класу), але інші ініціалізатори кріплення - ні. У цьому випадку я волів би помістити ініціалізацію в конструктор, який має чітко визначену семантику для успадкування :)


2
Це змінилося з NUnit 2.5. Тепер будуть викликані всі методи, позначені [TestFixtureSetup].
oderibas

-2

Конструктор і SetUpметоди використовуються по-різному:
конструктор запускається лише один раз.
Однак SetUpметоди запускаються кілька разів, перш ніж виконуватися кожен тестовий випадок.


1
Ви маєте на увазі [SetUp], тоді як OP посилається на [TestFixtureSetUp].
одного дня, коли
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.