Стандартні стандарти кодування тесту


22

Зазвичай, коли ми говоримо про стандарти кодування, ми посилаємося на код самої програми, але як бути з одиничними тестами? Чи існують певні рекомендації щодо стандартів кодування, які є унікальними для одиничних тестів? Хто вони?

Відповіді:


12

Я маю на увазі три відмінності стилю кодування для тестового коду.

При іменуванні методів тестування я слідую за схемою shouldDoSomethingWhenSomeConditionHolds.

Всередині тесту прийнято дотримуватися наступної схеми інтервалу:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

Деякі наполягають лише на одному твердженні за тест, але це далеко не універсальне.

DRY (не повторюй себе) менше враховує тестовий код, ніж виробничий код. Хоча деякий повторний код повинен бути розміщений у методі setUp або класі testUtils, прагнення до нульового повторення тестового коду призведе до жорстко пов'язаних і негнучких тестів, що відлякує рефакторинг.


Звичайно, існують найрізноманітніші зразки, саме тому вам слід надати відповідь.
Ерік Вілсон

10
Ось така схема " Упорядкувати, діяти", "затвердити" .
StuperUser

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

@MichaelFreidgeim Можливо, ми говоримо лише про градуси, але у мене значно вища толерантність до повторення тестового коду. У мене було кілька досвіду створення тестових наборів з дуже невеликим повторенням, і я виявив, що тести стали важко модифікувати та розуміти, коли вимоги змінювалися. Тоді я перестав хвилюватися стільки про DRY в тестах, і мої тестові набори були простішими у використанні. <shrug>
Ерік Вілсон

16

Рой Ошерово рекомендує наступний зразок для назви своїх тестів:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

Дивіться http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx


Я згоден з Роєм. Це покращує читанність, хоча ReSharper постійно говорить мені, що я повинен їх видалити NameOfMethodUnderTestStateUnderTestExpectedBehavior();)
Оскар Медерос

Як змусити цю роботу, коли метод перевантажений, так що може бути кілька методів з однаковою назвою?
Нарендра Патай

6

Головне пам’ятати, що одиничні тести по суті є міні-специфікаціями. Це означає, що акцент завжди повинен бути зроблений на читанні.

По-перше, це означає, що імена повинні чітко повідомляти про тестування і те, що стверджується.

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

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

Я лише завершу кілька книжкових рекомендацій:

Шаблони тестування xUnit: Тестовий код рефакторингу: Відмінна книга, деякі кажуть, що вона трохи суха, але я не думаю. Докладно описується багато різних способів організації тестів та способів їх збереження. Доречно, якщо ви використовуєте щось на зразок NUnit тощо.

Мистецтво одиничного тестування: з прикладами в. Net : Найкраща книга про солодкуватість написання та підтримки тестів. Незважаючи на те, що він є справді новим, я вважаю, що глузуючі розділи трохи датовані вже як синтаксис AAA - тепер досить стандартний, а не просто інший спосіб зробити це.

Вирощування об’єктно-орієнтованого програмного забезпечення, керуючись тестами : Ця книга просто дивовижна! На сьогоднішній день найкраща книга тестування одиниць і єдина вдосконалена книга, яка ставить тестування одиниць як першокласного громадянина в процесі проектування. Читав це, коли це була загальнодоступна бета-версія, і з тих пір рекомендую. Прекрасний реальний приклад, що працював у реальному світі, який використовується у всій книзі. Я б рекомендував спочатку прочитати книгу Роя.


IMHO нормально, щоб одиничні тести містили логіку: Цілком розумно перевірити високо оптимізовану, ефективну версію алгоритму, використовуючи наївний алгоритм, який робить те саме, щоб визначити правильну поведінку. Наприклад, уявіть тестування хеш-таблиці шляхом побудови лінійного асоціативного масиву на основі пошуку.
dimimcha

2
Так, але це належить поза тестом у розробниках тестових даних (які самі повинні бути перевірені одиницею, якщо логіка всередині них не тривіальна). Виняток з цього становлять сторонні бібліотеки, яким, як правило, «довіряють», що вони є правильними і можуть використовуватися без тестів.
FinnNk

3

Не вкладайте логіку у ваші одиничні тести. Наприклад, скажімо, ви тестуєте метод додавання, ви можете мати щось подібне:

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

У цьому конкретному випадку ви, ймовірно, повторюєте ту саму логіку, що і тест, тому ви по суті тестуєте "1 + 1 == 1 + 1", а не "1 + 1 == 2", що є "справжній" тест. Отже, як ви дійсно хотіли б виглядати ваш тестовий код:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}

2
Невелика корекція: я думаю, ви мали на увазі 'string очікувано = string.Format ("Привіт, Боб")' має бути 'string очікувано = "Hello, Bob"'.
Майк Розенблум

@MikeRosenblum ти, очевидно, маєш рацію, і хтось намагався її виправити, але два рецензенти відхилили цю редакцію
Конрад Моравський

@Konrad: це дивно. Це форум з програмування, правда?
Майк Розенблум

Я ще раз відредагував відповідь, як запропонував Майк Розенблум.
bdsl

0

Довгі описові назви методів. Пам'ятайте, що тестові методи ніколи не викликаються з коду (їх викликає блок-тестувальник, який виявляє та викликає їх за допомогою відображення), тому нормально сходити з розуму та мати назви методів довжиною 50-80 символів. Конкретна умова іменування (верблюд, випадок підкреслення, "повинен", "повинен", "коли", "дано" і т. Д.) Насправді не важлива, поки назва відповідає на три питання:

  • що тестується?
  • які умови?
  • який очікуваний результат?

Методи випробувань повинні бути короткими .

Методи випробувань повинні мати просту лінійну структуру . Ні, якщо або циклічні конструкції.

Методи випробувань повинні відповідати схемі "домовитись-затвердити" .

Кожен тест повинен перевірити одне . Зазвичай це означає одне твердження за тест. Тест на кшталт { Do A; Assert B; Assert C; }повинен бути перероблений на два: { Do A; Assert B; }і{ Do A; Assert C; }

Уникайте випадкових даних або таких речей, як "DateTime.Now"

Переконайтесь, що після закінчення випробування всі елементи кріплення для випробувань повертаються до їх початкового стану (наприклад, використовуючи тертя )

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


-1

Дещо подібний до того, що Farmboy вже згадував, Формат назви мого методу

 <MethodName>Should<actionPerformed>When<Condition>

напр

 GetBalanceShouldReturnAccountBalance() {
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.