Заставить каждый метод теста работать в своем собственном экземпляре класса теста с TestNG? - PullRequest
7 голосов
/ 30 апреля 2011

Поэтому я подумал, что следующий код будет нормально работать в TestNG, хотя это не так:

public class Tests {
    int i = 0;

    @Test
    public void testA() {
        Assert.assertEquals(0, i);
        ++i;
    }

    @Test
    public void testB() {
        Assert.assertEquals(0, i);
        ++i;
    }
}

Есть ли способ заставить TestNG запускать новый класс Tests для каждого метода тестирования?

Ответы [ 2 ]

4 голосов
/ 30 апреля 2011

Общим решением является использование метода @BeforeMethod для настройки состояния теста,

@BeforeMethod
public void setup() {
   i = 0; 
}
0 голосов
/ 30 мая 2018

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

private ThreadLocal<Integer> i = new ThreadLocal<>();

@BeforeMethod
public void setup() {
    i.set(0);
}

@Test
public void testA() {
    Integer i1 = i.get();
    Assert.assertEquals(0, i.get().intValue());
    i.set(i1 + 1);
}

@Test
public void testB() {
    Integer i1 = i.get();
    Assert.assertEquals(0, i.get().intValue());
    i.set(i1 + 1);
}

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

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

TestNG @Factory Factory позволяет вам создавать новые экземпляры ваших тестовых классов.

@Factory
public Object[] factory(){
    return new Object[]{new Tests(), new Tests()};
}

Я сейчас создал два Tests экземпляра, которые будут запускаться testNG

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

Вот грубый пример, который я взломал вместе.

public class TestFactory implements IMethodInterceptor {
    private List<String> methodsToRun = new ArrayList<>();
    private List<Object> testInstances = new ArrayList<>();

    @Factory
    public Object[] factory(){
        return new Object[]{new Tests(), new Tests()};
    }

    @Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        ArrayList<IMethodInstance> tempList = new ArrayList<>();
        for(IMethodInstance i: methods){
            if(testInstances.contains(i.getInstance())){
                continue;
            }
            String mName = i.getMethod().getConstructorOrMethod().getName();
            if(!methodsToRun.contains(mName)){
                tempList.add(i);
                methodsToRun.add(mName);
                testInstances.add(i.getInstance());
            }
        }
        return tempList;
    }
}

Затем добавьте своего слушателя в начало вашего Tests класса

@Listeners(TestFactory.class)

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

Возможно, сумасшедшее решение, подобное приведенному выше, подойдет вам или кому-то еще.

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