Как отключить тест TestNG на основе условия

Есть ли в настоящее время способ отключить тест TestNG на основе условия

Я знаю, что в настоящее время вы можете отключить тест как таковой в TestNG:

@Test(enabled=false, group={"blah"})
public void testCurrency(){
...
}

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

@Test(enabled={isUk() ? false : true), group={"blah"})
public void testCurrency(){
...
}

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


person Afamee    schedule 15.10.2010    source источник
comment
Аннотации не являются исполняемым кодом, так что это маловероятно. Что вы действительно пытаетесь сделать - в каких условиях вы хотите, чтобы тест выполнялся или не запускался?   -  person matt b    schedule 16.10.2010
comment
спасибо Мэтт. См. ответ cedrics ниже для более подробной информации.   -  person Afamee    schedule 16.10.2010


Ответы (7)


У вас есть два варианта:

Ваш преобразователь аннотаций проверит условие, а затем переопределит аннотацию @Test, чтобы добавить атрибут «enabled = false», если условие не выполняется.

person Cedric Beust    schedule 15.10.2010
comment
Спасибо, Седрик. Я думаю, что мне хотелось бы изучить опцию «трансформатор аннотаций». это больше похоже на то, что я ищу. - person Afamee; 16.10.2010
comment
Спасибо еще раз. Мне не потребовалось много времени, чтобы получить рабочий пример этого трансформатора. Одна вещь, хотя ведет себя не так, как я ожидал. Я хочу динамически преобразовать имя теста, который я запускаю (... по крайней мере, так, как оно будет отображаться в результате теста), вызвав annot.setTestName(concatString), где annot представляет аннотацию метода, но результат возвращается с исходным имя без изменений. Есть ли другой способ сделать это?? Надеюсь, не спутал вас. - person Afamee; 16.10.2010
comment
Вы не сможете переопределить поведение класса во время выполнения, так устроена Java. Вместо этого я предлагаю вам поместить логику, которая решает, что это за имя, непосредственно в тест, чтобы вы могли вернуть его в getTestName(). - person Cedric Beust; 16.10.2010
comment
это именно то, что я сделал. Я думал, что setTestName(newName) предназначен для изменения имени теста. Я понимаю вызов getTestName() для получения имени на основе логики в тестовом коде, но затем я хочу установить это вновь полученное имя для теста, сказав annot.setTestName(newName) или annot.setTestName(getTestName()+_Modified). Когда тест завершается, он по-прежнему имеет исходное имя, а не измененное имя. - person Afamee; 16.10.2010
comment
Можно ли этого достичь? - Я хочу отключить TestB, если TestA не прошел. - person Rameshwar; 06.09.2017

Более простой вариант — использовать аннотацию @BeforeMethod для метода, который проверяет ваше состояние. Если вы хотите пропустить тесты, просто создайте SkipException. Как это:

@BeforeMethod
protected void checkEnvironment() {
  if (!resourceAvailable) {
    throw new SkipException("Skipping tests because resource was not available.");
  }
}
person Bruce    schedule 13.12.2010
comment
Привет, так как 6.13 выбрасывание SkipException устанавливает статус Failed вместо Skiped. См. stackoverflow.com/questions/20022288/ - person Mike G.; 30.11.2017
comment
Документация SkipException относится к устаревшая аннотация @Configuration. Это может объяснить описанное поведение для @BeforeMethod и т. д. - person dpr; 26.04.2019
comment
Разве enabled=false проверка не происходит на еще более ранней стадии теста, чем BeforeMethod? В некоторых случаях использование enabled=false было бы лучше, чем использование Before-hook, ИМХО. - person djangofan; 15.05.2019

Есть два известных мне способа, позволяющих контролировать отключение тестов в TestNG.

Отличие, которое очень важно отметить, заключается в том, что SkipException прерывает все последующие тесты, в то время как реализация IAnnotationTransformer использует Reflection для отключения отдельных тестов на основе заданного вами условия. Я объясню как SkipException, так и IAnnotationTransfomer.

Пример исключения SKIP

import org.testng.*;
import org.testng.annotations.*;

public class TestSuite
{
    // You set this however you like.
    boolean myCondition;
    
    // Execute before each test is run
    @BeforeMethod
    public void before(Method methodName){
        // check condition, note once you condition is met the rest of the tests will be skipped as well
        if(myCondition)
            throw new SkipException();
    }
    
    @Test(priority = 1)
    public void test1(){}
    
    @Test(priority = 2)
    public void test2(){}
    
    @Test(priority = 3)
    public void test3(){}
}

Пример IAnnotationTransformer

Немного сложнее, но идея, лежащая в основе этого, — концепция, известная как Reflection.

Wiki — http://en.wikipedia.org/wiki/Reflection_(computer_programming)

Сначала реализуйте интерфейс IAnnotation, сохраните его в файле *.java.

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;

public class Transformer implements IAnnotationTransformer {

    // Do not worry about calling this method as testNG calls it behind the scenes before EVERY method (or test).
    // It will disable single tests, not the entire suite like SkipException
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod){

        // If we have chose not to run this test then disable it.
        if (disableMe()){
            annotation.setEnabled(false);
        }
    }

    // logic YOU control
    private boolean disableMe() {
    }
}

Затем в java-файле тестового набора выполните следующие действия в функции @BeforeClass.

import org.testng.*;
import org.testng.annotations.*;

/* Execute before the tests run. */    
@BeforeClass
public void before(){

    TestNG testNG = new TestNG();
    testNG.setAnnotationTransformer(new Transformer());
}

@Test(priority = 1)
public void test1(){}

@Test(priority = 2)
public void test2(){}

@Test(priority = 3)
public void test3(){}

Последний шаг — убедиться, что вы добавили прослушиватель в файл build.xml. У меня получилось вот так, это всего лишь одна строка из build.xml:

<testng classpath="${test.classpath}:${build.dir}" outputdir="${report.dir}" 
    haltonfailure="false" useDefaultListeners="true"
    listeners="org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter,Transformer" 
    classpathref="reportnglibs"></testng>
person Makeen A. Sabree    schedule 18.03.2014

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

  • Использование аннотации @Assumment
  • Использование AssummentListener Использование метода Assumes.assumeThat(...)

Вы можете использовать этот пример: пример

person avivamg    schedule 22.07.2018

Я предпочитаю этот способ на основе аннотаций для отключения/пропуска некоторых тестов на основе настроек среды. Простота в обслуживании и не требует какой-либо специальной техники кодирования.

  • Использование интерфейса IInvokedMethodListener
  • Создайте пользовательскую аннотацию, например: @SkipInHeadlessMode.
  • Бросить SkipException
public class ConditionalSkipTestAnalyzer implements IInvokedMethodListener {
    protected static PropertiesHandler properties = new PropertiesHandler();

    @Override
    public void beforeInvocation(IInvokedMethod invokedMethod, ITestResult result) {
        Method method = result.getMethod().getConstructorOrMethod().getMethod();
        if (method == null) {
            return;
        }
        if (method.isAnnotationPresent(SkipInHeadlessMode.class)
                && properties.isHeadlessMode()) {
            throw new SkipException("These Tests shouldn't be run in HEADLESS mode!");
        }
    }

    @Override
    public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        //Auto generated
    }
}

Проверьте подробности: https://www.lenar.io/skip-testng-tests-based-condition-using-iinvokedmethodlistener/

person Tóth Krisztián Gyula    schedule 10.02.2020

Выброс SkipException в методе с аннотацией @BeforeMethod у меня не сработал, потому что он пропускал все оставшиеся тесты моего набора тестов, независимо от того, были ли выброшены SkipException для этих тестов.

Я не исследовал это тщательно, но нашел другой способ: используя атрибут dependsOnMethods в аннотации @Test:

import org.testng.SkipException;
import org.testng.annotations.Test;

public class MyTest {

  private boolean conditionX = true;
  private boolean conditionY = false;

  @Test
  public void isConditionX(){
    if(!conditionX){
      throw new SkipException("skipped because of X is false");
    }
  }

  @Test
  public void isConditionY(){
    if(!conditionY){
      throw new SkipException("skipped because of Y is false");
    }
  }

  @Test(dependsOnMethods="isConditionX")
  public void test1(){

  }

  @Test(dependsOnMethods="isConditionY")
  public void test2(){

  }
}
person letrait    schedule 18.04.2017

SkipException: полезно, если у нас есть только один метод @Test в классе. Как и в случае с Data Driven Framework, у меня есть только один тестовый метод, который нужно либо выполнить, либо пропустить на основании некоторого условия. Поэтому я поместил логику проверки условия в метод @Test и получил желаемый результат. Это помогло мне получить отчет об объеме с результатами тестового примера как Pass/Fail и, в частности, Skip.

person PAQuality101    schedule 18.01.2019