В моем проекте есть пары тестов, которые я хотел бы запускать последовательно отдельными методами. Обычно я бы использовал DataProvider для генерации входных данных для теста:

@DataProvider
public Object[][] getUsers() {
    // generate input for test2();
}

@Test(dataProvider = "getUsers")
public void test2(User user) {
    assertSomething(user);
}

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

Вот и хотелось бы примерно такого:

@Test
public Object test1() {
    User user = createUser();
    assertSomething(user);

    return user.getProperty();
}

@Test // depends on test1 - I do not want to execute this test if test1 fails.
public void test2(Object userProperty) {
    assertSomethingElse(userProperty);
}

На самом деле я мог бы перенести логику с test1 на test2, чтобы достичь того, чего хочу, но мне было интересно, есть ли более разумные способы сделать это.

0
Eugene A 26 Фев 2016 в 17:03

3 ответа

Лучший ответ

Да, выход есть. Думаю, что-то вроде этого вы и хотите. В отличие от JUnit, TestNG позволяет подключиться до запуска тестового метода и получить доступ к аргументам вашего тестового метода, вроде как в случае с AOP:

@DataProvider
public Object[][] getUsers() {
    int[][] multi = new int[][]{
       { 0, new User("Tom") },
       { 0, new User("Sally") }
    };
    return multi;
}

@BeforeMethod
public void setupBeforeEachTest(Object[] args) {
    User x = (User)args[1];
    x.modify();
}

@Test(dataProvider = "getUsers")
public void test1(User user) {
    assertSomething(user);
}

@Test(dataProvider = "getUsers")
public void test2(User user) {
    assertSomethingElse(user);
}
1
djangofan 29 Фев 2016 в 19:05

Вот решение, которое будет работать независимо от того, запускаете ли вы другие комплекты параллельно. Параметр supportsOnMethods гарантирует, что test2 будет выполняться после прохождения теста 1. Идея состоит в том, чтобы реализовать фабрику:

Ваши методы тестирования будут выглядеть примерно так:

@Test
public void test1(ITestContext context) {
    User objUser = Factory.getUser(context.getName());
    assertSomething(objUser);
}

@Test(dependsOnMethods = "test1")
public void test2(ITestContext context) {    assertSomethingElse(Factory.getUser(context.getName()).getProperty());
}

Заводской класс будет примерно таким:

public class Factory
{
static Map<testName,User> mainMap;

//This method returns User object to a test based on the test name.
public static User getUser(String testName)
{
if (mainMap == null)
{
    mainMap = new HashTable<testName,User>();
    mainMap.put(testName,new User());
}
if(!mainMap.contains(testName))
{
    mainMap.put(testName,new User());
}

return mainMap.get(testName);
}
}

Для получения дополнительной информации о теории обмена объектами между методами / потоками с использованием factory обратитесь к следующему: http://singinginthesunlight.blogspot.in/2016 /02/testng-parallelism-kiss-of-death-or.html

0
Surbhi Sharma 27 Фев 2016 в 11:13

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

Если вас не беспокоит параллелизм, тогда поле члена класса работает нормально:

private User user;

@Test
public void test1() {
    user = createUser();
    assertSomething(user);
}

@Test(dependsOnMethods = "test1")
public void test2() {
    assertSomethingElse(user.getProperty());
}

Если вы действительно хотите иметь возможность запускать несколько экземпляров тестового класса параллельно, вам нужно использовать что-то вроде ThreadLocal<T>:

private static final ThreadLocal<User> USERS = new InheritableThreadLocal<>();

@Test
public void test1() {
    USERS.set(createUser());
    assertSomething(user);
}

@Test(dependsOnMethods = "test1")
public void test2() {
    assertSomethingElse(USERS.get().getProperty());
}
0
mfulton26 26 Фев 2016 в 14:52