Статьи

Правила в JUnit 4.9 (бета 3)

Некоторое время назад Дэвид Сафф объявил о выпуске бета-версии JUnit 4.9 . Поэтому я думаю, что сейчас самое время посмотреть, что нового в этой версии .

Одним из наиболее полезных нововведений в области JUnit были Правила. Я написал о правилах здесь . И я написал о случаях использования для правил JUnit здесь . Правила отличные. А с JUnit 4.9 они становятся еще лучше.

Вы можете думать о Правилах как о способе инкапсулировать установку и разбор теста в одном классе вместо двух методов. Но правила также способ изменить способ выполнения ваших тестов. Вы можете запускать тесты десятки раз вместо одного раза. Или в двадцати разных темах. Интересно, что были только Правила для одиночных испытаний. Поэтому, если вы хотите придерживаться сравнения с настройкой и разборкой, то есть, @Before и @After, в правилах не было эквивалента @BeforeClass и @AfterClass .

Теперь это изменилось. Теперь вы можете аннотировать открытое статическое поле типа TestRule с помощью @ClassRule, и оно будет вести себя подобно правилу, которое определено для всего класса теста, а не для одного теста. Так что он идеально подходит для вещей, которые нужно настроить один раз для всех тестов, а не для каждого теста. Давайте посмотрим на пример.

Реализация правила может выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
  
public class LoggingRule implements TestRule {
  
 public class LoggingStatement extends Statement {
  
  private final Statement statement;
  
  public LoggingStatement(Statement aStatement, String aName) {
   statement = aStatement;
  }
  
  @Override
  public void evaluate() throws Throwable {
   System.out.println("before: " + name);
   statement.evaluate();
   System.out.println("after: " + name);
  }
  
 }
  
 private final String name;
  
 public LoggingRule(String aName) {
  name = aName;
 }
  
 @Override
 public Statement apply(Statement statement, Description description) {
  System.out.println("apply: " + name);
  
  return new LoggingStatement(statement, name);
 }
  
}

Большинство реализаций будет состоять из двух частей: реализация интерфейса TestRule и реализация интерфейса Statement.

TestRule заменяет устаревший интерфейс MethodRule, который использовался ранее. Это связано с тем, что новый интерфейс поддерживает оба правила на уровне класса и на уровне метода, поэтому его пришлось немного изменить. TestRule имеет единственный метод apply, который принимает Statement и возвращает Statement . Этот метод вызывается перед выполнением любого теста в области действия правила. Переданное утверждение фактически является тестами, которые могут быть выполнены. Здесь следует отметить две вещи: Statement может и будет представлять несколько тестов, если ваше правило будет использоваться с аннотацией @ClassRule ; И призыв применить не означает, что Заявление будет фактически выполнено. Так как все ваши возвраты Правил могут быть переданы другим Правилам, операторы могут быть искажены различными способами, прежде чем содержащиеся в них тесты будут фактически выполнены. Типичная вещь в методе apply — заключить оператор в новый оператор, который будет выполнять любую логику, необходимую для вашей цели.

Интерфейс Statement имеет единственный метод оценки, который должен выполнить тест или набор тестов в обычном случае. Поэтому, если вы придерживаетесь типичного подхода, упомянутого выше, вы выполняете некоторую оценку вызова установки для содержащегося в нем оператора и выполняете некоторые операции. В приведенном выше примере я печатаю материал на консоли, чтобы видеть, в каком порядке вызывается материал. Оператор также получает описание, которое содержит полезную мета-информацию о тесте (-ах). Он содержит имя, класс, в котором определен тест, имя метода и делает доступными аннотации. Таким образом, ваше Правило / Заявление может точно настроить его поведение на основе метода тестирования, с которым он работает.

Тестовый класс, использующий это правило, может выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
  
public class RuleTest {
  
 @ClassRule
 public static LoggingRule classRule = new LoggingRule("classrule");
  
 @Rule
 public static LoggingRule rule = new LoggingRule("rule");
  
 @Test
 public void testSomething() {
  System.out.println("In TestSomething");
  assertTrue(true);
 }
  
 @Test
 public void testSomethingElse() {
  System.out.println("In TestSomethingElse");
  assertTrue(true);
 }
}

Единственное изменение в правилах JUnit4.8 — это наличие аннотации @ClassRule . Обратите внимание, что один и тот же класс используется с аннотациями @ClassRule и @Rule .
При выполнении вывод тестового класса выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
apply: classrule
before: classrule
apply: rule
before: rule
In TestSomething
after: rule
apply: rule
before: rule
In TestSomethingElse
after: rule
after: classrule

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

Ссылка: правила в JUnit 4.9 (бета 3) от нашего партнера JCG Йенса Шаудера в блоге Schauderhaft .

Статьи по Теме :