Как запустить методы тестирования в определенном порядке в JUnit4?
Я хочу выполнить методы тестирования, которые аннотируются @Test
в особом порядке.
например:
public class MyTest {
@Test public void test1(){}
@Test public void test2(){}
}
Я хочу, чтобы запустить test1()
до test2()
каждый раз, когда я запустить MyTest
, но я не мог найти аннотацию, как @Test(order=xx)
.
Я думаю, что это довольно важная функция для JUnit, если автор JUnit не хочет функция порядка, почему?
16 ответов:
Я думаю, что это довольно важная функция для JUnit, если автор JUnit не хочет функцию заказа, почему?
Я не уверен, что есть чистый способ сделать это с JUnit, насколько мне известно, JUnit предполагает, что все тесты могут быть выполнены в произвольном порядке. Из FAQ:
как я использую приспособление теста?
(...) Порядок вызовов метода тестирования не гарантируется, так testOneItemCollection () может быть выполнен до testEmptyCollection (). (...)
почему это так? Ну, я считаю, что делать тесты зависит от того это практика, которую авторы не хотят продвигать. Тесты должны быть независимыми, они не должны быть связаны и нарушать это будет сделать вещи труднее поддерживать, сломает возможность запускать тесты индивидуально (очевидно) и т. д.
Это, как говорится, если вы действительно хотите пойти в в этом направлении рассмотрите возможность использования TestNG, поскольку он поддерживает выполнение методов тестов в любом произвольном порядке изначально (и такие вещи, как указание, что методы зависят от групп методов). Седрик Бест объясняет, как это сделать в порядок выполнения тестов в testng.
Если вы избавитесь от существующего экземпляра Junit и загрузите JUnit 4.11 или больше в пути сборки, следующий код будет выполнять методы тестирования в порядке их имен, отсортированных в порядке возрастания:
@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SampleTest { @Test public void testAcreate() { System.out.println("first"); } @Test public void testBupdate() { System.out.println("second"); } @Test public void testCdelete() { System.out.println("third"); } }
если заказ важен, вы должны сделать заказ самостоятельно.
@Test public void test1() { ... } @Test public void test2() { test1(); ... }
в частности, вы должны перечислить некоторые или все возможные перестановки порядка для тестирования, если это необходимо.
например,
void test1(); void test2(); void test3(); @Test public void testOrder1() { test1(); test3(); } @Test(expected = Exception.class) public void testOrder2() { test2(); test3(); test1(); } @Test(expected = NullPointerException.class) public void testOrder3() { test3(); test1(); test2(); }
или, полный тест всех перестановок:
@Test public void testAllOrders() { for (Object[] sample: permute(1, 2, 3)) { for (Object index: sample) { switch (((Integer) index).intValue()) { case 1: test1(); break; case 2: test2(); break; case 3: test3(); break; } } } }
здесь
permute()
Это простая функция, которая повторяет все возможные перестановки в коллекцию массива.
миграция в TestNG кажется лучшим способом, но я не вижу здесь четкого решения для jUnit. Вот самое прочитать решение / форматирование Я нашел для jUnit:
@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SampleTest { @Test void stage1_prepareAndTest(){}; @Test void stage2_checkSomething(){}; @Test void stage2_checkSomethingElse(){}; @Test void stage3_thisDependsOnStage2(){}; @Test void callTimeDoesntMatter(){} }
это гарантирует, что методы stage2 вызываются после stage1 и перед stage3.
Это одна из главных проблем, с которой я столкнулся, когда работал над Junit, и я придумал следующее решение, которое отлично работает для меня:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; public class OrderedRunner extends BlockJUnit4ClassRunner { public OrderedRunner(Class<?> clazz) throws InitializationError { super(clazz); } @Override protected List<FrameworkMethod> computeTestMethods() { List<FrameworkMethod> list = super.computeTestMethods(); List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list); Collections.sort(copy, new Comparator<FrameworkMethod>() { @Override public int compare(FrameworkMethod f1, FrameworkMethod f2) { Order o1 = f1.getAnnotation(Order.class); Order o2 = f2.getAnnotation(Order.class); if (o1 == null || o2 == null) { return -1; } return o1.order() - o2.order(); } }); return copy; } }
также создать интерфейс, как показано ниже:
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD}) public @interface Order { public int order(); }
Теперь предположим, что у вас есть класс A, где вы написали несколько тестовых случаев, как показано ниже:
(@runWith=OrderRunner.class) Class A{ @Test @Order(order = 1) void method(){ //do something } }
таким образом, выполнение начнется с метода с именем "method()". Спасибо!
изменение (пока еще не выпущено)https://github.com/junit-team/junit/pull/386 вводит
@SortMethodsWith
. https://github.com/junit-team/junit/pull/293 по крайней мере, сделал порядок предсказуемым без этого (в Java 7 он может быть довольно случайным).
посмотрите на отчет JUnit. JUnit уже организован пакетом. Каждый пакет имеет (или может иметь) классы TestSuite, каждый из которых, в свою очередь, запускает несколько тестовых наборов. Каждый тестовый случай может иметь несколько методов тестирования формы
public void test*()
, каждый из которых фактически станет экземпляром класса TestCase, к которому они принадлежат. Каждый метод тестирования (экземпляр TestCase) имеет имя и критерии прохождения/сбоя.то, что требуется моему менеджменту, - это концепция индивидуального TestStep элементы, каждый из которых сообщает свои собственные критерии прохождения/отказа. Отказ любого шага теста не должен препятствовать выполнению последующих шагов теста.
методы TestCase были шагами TestCase, и разработчики тестов получили отдельный критерий pass/fail на шаг теста. Теперь шаги теста перемешаны, и тесты (конечно) терпят неудачу.
например:
Class testStateChanges extends TestCase public void testCreateObjectPlacesTheObjectInStateA() public void testTransitionToStateBAndValidateStateB() public void testTransitionToStateCAndValidateStateC() public void testTryToDeleteObjectinStateCAndValidateObjectStillExists() public void testTransitionToStateAAndValidateStateA() public void testDeleteObjectInStateAAndObjectDoesNotExist() public void cleanupIfAnythingWentWrong()
каждый метод теста утверждает и сообщает свои собственные отдельные критерии пропуска/отказа. Свернув это в "один большой метод тестирования "ради упорядочения теряет гранулярность критериев прохождения/отказа каждого" шага " в сводном отчете JUnit. ...и это расстраивает моих менеджеров. В настоящее время они требуют другой альтернативы.
может ли кто-нибудь объяснить, как JUnit с упорядочением метода скремблированного теста будет поддерживать отдельные критерии прохождения/сбоя каждого последовательного шага теста, как показано выше и требуется моим руководством?
независимо от документации, я вижу это как серьезное регрессия в рамках JUnit, что делает жизнь трудной для многих разработчиков тестов.
то, что вы хотите, совершенно разумно, когда тестовые случаи выполняются как набор.
к сожалению, нет времени, чтобы дать полное решение прямо сейчас, но посмотрите на класс:
org.junit.runners.Suite
что позволяет вызывать тестовые случаи (из любого тестового класса) в определенном порядке.
они могут быть использованы для создания функционального, интеграционного и системного тестирования.
это оставляет ваши модульные тесты, как они без определенного порядка (как рекомендуется), ли вы запустите их так или иначе, а затем повторно используйте тесты как часть более широкой картины.
мы повторно используем / наследуем один и тот же код для модульных, интеграционных и системных тестов, иногда управляемых данными, иногда управляемых фиксацией, а иногда запускаемых как набор.
Не уверен, что я согласен, Если я хочу проверить "загрузку файла", а затем проверить "данные, вставленные При загрузке файла", почему я не хочу, чтобы они были независимы друг от друга? Вполне разумно, я думаю, чтобы иметь возможность запускать их отдельно, а не иметь оба в тестовом случае Голиафа.
посмотреть мое решение здесь: "Junit и java 7."
в этой статье я описываю, как запускать тесты junit по порядку - "так же, как в вашем исходном коде". Тесты будут запущены, чтобы ваши методы тестирования отображались в файле класса.
http://intellijava.blogspot.com/2012/05/junit-and-java-7.html
Я прочитал несколько ответов и согласен, что это не лучшая практика, но самый простой способ заказать ваши тесты - и способ, которым JUnit запускает тесты по умолчанию, - это алфавитное имя по возрастанию.
поэтому просто назовите свои тесты в алфавитном порядке, который вы хотите. Также обратите внимание, что имя теста должно начинаться со словом тест. Просто следите за номерами!--1-->
test12 будет работать до условие_2
Так:
testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond
пожалуйста, проверьте это:https://github.com/TransparentMarket/junit. он запускает тест в том порядке, в котором они указаны (определены в скомпилированном файле класса). Кроме того, он имеет набор AllTests для запуска тестов, определенных субпакетом в первую очередь. Используя реализацию AllTests, можно расширить решение и в фильтрации свойств (мы использовали аннотации @Fast, но они еще не были опубликованы).
вот расширение для JUnit, которое может производить желаемое поведение:https://github.com/aafuks/aaf-junit
Я знаю, что это против авторов философии JUnit, но при использовании JUnit в средах, которые не являются строгим модульным тестированием (как это практикуется в Java), это может быть очень полезно.
Я закончил здесь, думая, что мои тесты не были запущены в порядке, но правда в том, что беспорядок был в моих асинхронных заданиях. При работе с параллелизмом необходимо также выполнять проверки параллелизма между тестами. В моем случае задания и тесты совместно используют семафор, поэтому следующие тесты зависают до тех пор, пока выполняемое задание не освободит блокировку.
Я знаю, что это не полностью связано с этим вопросом, но, возможно, может помочь нацелиться на правильную проблему
вы можете использовать один из этих кусок кода:
@FixMethodOrder(MethodSorters.JVM)OR `@FixMethodOrder(MethodSorters.DEFAULT)` OR `@FixMethodOrder(MethodSorters.NAME_ASCENDING)` before your test class like this: @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class BookTest { ...}
JUnit в настоящее время позволяет тестовым методам выполнять упорядочение с использованием аннотаций классов:
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.JVM) @FixMethodOrder(MethodSorters.DEFAULT)
установить способов заказа вы можете назвать их так:
a_testWorkUnit_WithCertainState_shoulddosomething b_testWorkUnit_WithCertainState_shoulddosomething c_testWorkUnit_WithCertainState_shoulddosomething
вы можете найти вот примеры:.