在TestNG中执行测试的顺序问题

时间:2017-10-14 20:15:41

标签: selenium selenium-webdriver automated-tests testng

我有一个包 - '脚本'

在脚本下,我有两个类--A和B

在A类下我按顺序编写了3个方法(@Test) -

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

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

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

在B级下我有1个方法 -

@Test
public void c(){}

的testng.xml

<classes>
  <class name="scripts.A"/>
  <class name="scripts.B"/>
</classes>

On Execution-作为TestNG Suite - 右键单击​​TestNG XML并选择Run作为TestNG Suite运行

  1. B类首先执行 - 这是因为B类中的@Test没有指定优先级因此成为最高优先级
  2. @Test的优先级是否只能在类中重要?为什么TestNG会比较所有类中所有测试方法的优先级,然后计划执行。 此外,由于我在TestNG XML中定义类的执行顺序,显然我希望在第一类方法之后执行第二类方法。在这种情况下,预期的执行顺序应首先是A方法,然后是B方法。

    1. 当我从每个@Test和开始执行中删除优先级时,执行不会按照编写方法的顺序发生。实际上,执行以方法名称的升序开始。在这种情况下,order is- a(),b(),c(),d()
    2. 如何逃脱?

1 个答案:

答案 0 :(得分:0)

默认情况下,TestNG首先收集所有方法,然后根据它们的优先级对它们进行排序(它不会在它们之前出现的类中对它们进行分类)。话虽如此,这就是你如何做到的。

  1. 首先确保您的@Test方法不使用优先级属性(或),您已在套件xml文件中明确将preserve-order设置为false
  2. 然后构建一个方法拦截器,它首先根据类xml文件中出现的类的顺序对方法进行排序,然后使用自定义注释,这种注释使用相同的优先级排序机制。
  3. 这应该照顾你的需要。

    这是你的A课程相似:

    import org.testng.ITestResult;
    import org.testng.Reporter;
    import org.testng.annotations.Test;
    
    public class TestClassASample {
        @Test
        @PriorityInClass(priority = 1)
        public void a() {
            System.err.println(stringify());
        }
    
        @Test
        @PriorityInClass(priority = 2)
        public void b() {
            System.err.println(stringify());
        }
    
        @Test
        @PriorityInClass(priority = 3)
        public void c() {
            System.err.println(stringify());
        }
    
        private String stringify() {
            ITestResult result = Reporter.getCurrentTestResult();
            return result.getTestClass().getRealClass().getName() + "." + result.getMethod().getMethodName() + "()";
        }
    }
    

    这是你的B课程相似:

    import org.testng.ITestResult;
    import org.testng.Reporter;
    import org.testng.annotations.Test;
    
    public class TestClassBSample {
        @Test
        public void c() {
            System.err.println(stringify());
        }
    
        private String stringify() {
            ITestResult result = Reporter.getCurrentTestResult();
            return result.getTestClass().getRealClass().getName() + "." + result.getMethod().getMethodName() + "()";
        }
    }
    

    以下是您的自定义注释的外观:

    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.METHOD;
    
    @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
    @Target({METHOD})
    public @interface PriorityInClass {
        int priority() default 0;
    }
    

    以下是方法拦截器的外观:

    import org.testng.IMethodInstance;
    import org.testng.IMethodInterceptor;
    import org.testng.ITestContext;
    import org.testng.xml.XmlClass;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    public class MethodOrderer implements IMethodInterceptor {
        @Override
        public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
            Map<Class, List<IMethodInstance>> mapping = new LinkedHashMap<>();
            List<XmlClass> xmlClasses = context.getCurrentXmlTest().getXmlClasses();
            for (XmlClass xmlClass : xmlClasses) {
                Class<?> clazz = xmlClass.getSupportClass();
                mapping.put(clazz, new ArrayList<>());
                for (IMethodInstance method : methods) {
                    Class<?> methodClass = method.getMethod().getTestClass().getRealClass();
                    if (mapping.containsKey(methodClass)) {
                        List<IMethodInstance> methodInstances = mapping.get(methodClass);
                        if (!methodInstances.contains(method)) {
                            methodInstances.add(method);
                        }
                    }
                }
            }
            List<IMethodInstance> returnValue = new ArrayList<>(methods.size());
            Sorter sorter = new Sorter();
            for (Map.Entry<Class, List<IMethodInstance>> each : mapping.entrySet()) {
                List<IMethodInstance> methodInstances = each.getValue();
                Collections.sort(methodInstances, sorter);
                returnValue.addAll(methodInstances);
            }
            return returnValue;
        }
    
        public static class Sorter implements Comparator<IMethodInstance> {
    
            @Override
            public int compare(IMethodInstance o1, IMethodInstance o2) {
                PriorityInClass o1Priority = getPriority(o1);
                PriorityInClass o2Priority = getPriority(o2);
                int priorityO1 = (o1Priority == null ? getPriorityViaTestAnnotation(o1) : o1Priority.priority());
                int priorityO2 = (o2Priority == null ? getPriorityViaTestAnnotation(o1) : o2Priority.priority());
                return (priorityO1 < priorityO2) ? -1 : ((priorityO1 == priorityO2) ? 0 : 1);
            }
    
            private PriorityInClass getPriority(IMethodInstance instance) {
                return instance.getMethod().getConstructorOrMethod().getMethod().getAnnotation(PriorityInClass.class);
            }
    
            private int getPriorityViaTestAnnotation(IMethodInstance instance) {
                return instance.getMethod().getPriority();
            }
        }
    }
    

    以下是套件xml的外观

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="suite">
        <listeners>
            <listener class-name="com.rationaleemotions.stackoverflow.qn46748930.MethodOrderer"/>
        </listeners>
        <test name="random_test"  preserve-order="false">
            <classes>
                <class name="com.rationaleemotions.stackoverflow.qn46748930.TestClassASample"/>
                <class name="com.rationaleemotions.stackoverflow.qn46748930.TestClassBSample"/>
            </classes>
        </test> <!-- random_test -->
    </suite> <!-- suite -->
    

    这是输出:

    com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.a()
    com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.b()
    com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.c()
    com.rationaleemotions.stackoverflow.qn46748930.TestClassBSample.c()
    
    ===============================================
    suite
    Total tests run: 4, Failures: 0, Skips: 0
    ===============================================