Подтвердить что ты не робот

Единичное тестирование: почему ожидаемый аргумент всегда всегда в тестах равенства?

Почему каждая инфраструктура тестирования модулей (я знаю:) требует, чтобы ожидаемое значение в тестах равенства всегда было первым аргументом:

Assert.AreEqual(42, Util.GetAnswerToLifeTheUniverseAndEverything());

assertEquals(42, Util.GetAnswerToLifeTheUniverseAndEverything());

и др.

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

4b9b3361

Ответ 1

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

if (4 == myVar)

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

Ответ 2

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

В утверждении мы хотим убедиться, что некоторый объект соответствует некоторым условиям. Это естественная форма языка, как если бы вы объяснили свой тестовый код, который вы, вероятно, скажете

"В этом тесте я убеждаюсь, что вычисленное значение равно 5"

вместо

"В этом тесте я убеждаюсь, что 5 равно вычисленному значению".

Разница может не быть огромной, но пусть она будет продвигаться дальше. Рассмотрим это:

Assert.That(Roses, Are(Red));

Звучит правильно. Сейчас:

Assert.That(Red, Are(Roses));

Хм..? Вероятно, вы не были бы слишком удивлены, если бы кто-то сказал вам, что розы красные. Другой способ, красный - розы, вызывает подозрительные вопросы. Yoda, кто-нибудь?

That doesn't sound natural at all

Йода делает важный момент - обратный порядок заставляет вас думать.

Это становится еще более неестественным, когда ваши утверждения более сложны:

Assert.That(Forest, Has.MoreThan(15, Trees));

Как бы вы отменили это? Более 15 деревьев находятся в лесу?

Эта претензия (беглость как движущий фактор для модификации) каким-то образом отражается в изменении, которое NUnit прошло - изначально (Assert.AreEqual) он ожидал до фактического (старый стиль). Свободные расширения (или использовать терминологию NUnit, основанную на ограничениях - Assert.That) отменили этот порядок.

Ответ 3

Никто не знает, и это источник бесконечных путаниц. Однако не все рамки следуют этому шаблону (к большей путанице):

  • FEST-Assert использует обычный порядок:

    assertThat(Util.GetAnswerToLifeTheUniverseAndEverything()).isEqualTo(42);
    
  • Hamcrest:

    assertThat(Util.GetAnswerToLifeTheUniverseAndEverything(), equalTo(42))
    
  • ScalaTest не делает отличия:

    Util.GetAnswerToLifeTheUniverseAndEverything() should equal (42)
    

Ответ 4

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

Есть много людей, которые думают

if (42 == answer) {
  doSomething();
}

предпочтительнее

if (answer == 42) {
  doSomething();
}

на языках C. Причина этого в том, что если вы случайно положили один знак равенства:

if (42 = answer) {
  doSomething();
}

даст вам ошибку компилятора, но

if (answer = 42) {
  doSomething();
}

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

Ответ 5

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

почему JUnit сделал это именно так? Я не знаю, спросите Кент Бек!

Ответ 6

Ну, им нужно было выбрать одно соглашение. Если вы хотите повернуть вспять, попробуйте разборщики Hamcrest. Они предназначены для повышения удобочитаемости. Вот базовый пример:

import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.hamcrest.core.Is.is;

public HamcrestTest{
   @Test
   public void matcherShouldWork(){
       assertThat(   Math.pow( 2, 3 ),  is( 8 )  );
   }
}

Ответ 7

Конечно, логично предположить, что первое значение будет иметь ожидаемое значение, так как это первое известное значение.

Подумайте об этом в контексте ручных тестов. Ручной тест будет иметь ожидаемое значение, записанное с последующим фактическим значением.