【问题标题】:TestNG: How can I run same test case multiple times?TestNG:如何多次运行相同的测试用例?
【发布时间】:2014-11-25 12:31:22
【问题描述】:

我想多次运行一个测试用例。可以在testng.xml 中配置吗?如果我在测试方法中添加一个循环,那么testng报告中每次运行的结果都不会受到影响。

【问题讨论】:

  • 我怎样才能多次运行相同的测试,但在这些时间之间我运行其他测试方法?

标签: testng


【解决方案1】:

您无法从 xml 中执行此操作,但在 @Test 注释中 - 您可以添加一个 invocationCount 属性,其中包含您想要运行它的次数。它会随着报告中运行的许多测试而出现。

例如。

@Test(invocationCount = 10)
public void testCount() {..}

你错过了结尾的大括号,所以稍微更正一下。

【讨论】:

  • 这太糟糕了,因为对于某些用例来说,能够在 XML 而不是代码中进行配置非常重要。例如:我有一个功能测试用例 purchaseXYZ()。在我的功能测试套件中,我只想运行一次以查看是否有任何问题。在我的性能测试套件中,我想运行 100 次以获得平均延迟。因此,我需要能够指定来自 XML 的调用次数,而不是在代码中硬编码。
  • 为什么不做第二个测试——一个用于功能测试,一个用于单元测试?
  • @anon58192932 虽然我认为这可行,但它似乎更像是一种解决方法而不是解决方案。
  • @JohnChesshir 最好的解决方案通常是最容易实施的解决方法,因为似乎总是有更大的问题需要解决。
  • @anon58192932 是的。不过,我只是一个注重细节的人,你可以看到我自己的答案。
【解决方案2】:

TestNg 有一种方法。您可以使用此方法并多次运行您的测试用例:

@Test(invocationCount = 100)

public void testCount() {

}

【讨论】:

  • 能否请edit 回答并澄清您的意思?就目前而言,我不明白您是在给出新答案还是在评论niharika_neo's answer。如果你想问一些关于它的问题,你应该在一个新问题中提问,而不是在这里。这是一个问答网站,不是论坛。谢谢!
【解决方案3】:

到目前为止,没有一个答案真正让用户能够从 testng 文件中增加调用次数,这正是所要求的。该解决方案借鉴了 gaurav25 的 DataProvider 解决方案。

class TestClass() {
    int invocations;

    @Parameters({ "invocationCount" })
    @BeginClass
    void BeginClass( @Optional("1") String invocationCount) {
        this.invocations = Ingeter.parse(invocationCount)
    }

    // It will return a 2D array of size 3x1
    @DataProvider(name="URLprovider")
    private Object[][] getURLs() {
        ArrayList<Object []> obj = new ArrayList<>(3 * this.invocations);

        for(int iCount = 0; iCount < this.invocations; ++iCount) {
            list.add( new Object[] {"https://www.google.co.in/"} );
            list.add( new Object[] {"http://www.gmail.com/"} );
            list.add( new Object[] {"http://stackoverflow.com/"} );
        }

        return list.toArray();
    }

    /* Since Data provider for this test method returns 2D array of size
     (3*invocations)x1, this test method will run 3*invocations 
     times **automatically** with 1 parameter every time. */
    @Test(dataProvider="URLprovider")
    private void notePrice(String url) {
        driver.get(url);
        System.out.println(driver.getTitle());  
    }
}

现在您可以使用这个 testng.xml 文件更改通过测试函数运行的测试集数量:

<suite name="ESFService" verbose="1" parallel="methods" thread-count="1" data-provider-thread-count="10" >
    <test name="Basic">
        <classes>
            <class name="TestClass">
                <parameter name="invocationCount" value="5"/>
            </class>
        </classes>
    </test>
</suite>

【讨论】:

  • 在这段代码中,我的小毛病对 String invocationCount 和 int invocationCount 使用了相同的变量名。这总是会导致混乱和可能的错误。并且您的方法 getURls() 列表未定义。
  • @JPM 点 invocationCount。我已将成员变量和所有使用它的地方更改为“调用”。关于getURLs(),方法是明确定义的。我想你可能是想说它永远不会“使用”。按照这个假设,尽管确实从未直接调用该方法,但它是通过分配给它的 DataProvider 注释使用的。请注意,注释将属性“name”设置为“URLprovider”。然后通过将其 dataProvider 属性设置为相同的值,notePrice 函数上的 Test 注释会引用该值。
【解决方案4】:

我很晚才知道,但如果你的目标是每次运行都获得报告,那么你可以试试 TestNG Listener IAnnotationTransformer

代码片段

public class Count implements IAnnotationTransformer {

    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        // TODO Auto-generated method stub
        annotation.setInvocationCount(numberOfTimesTOExecute);
    }

xml sn-p

<listeners>
<listener class-name="multiple.Count"></listener>

【讨论】:

  • 这看起来不错。但是你能得到从 testng.xml 文件中填充的 numberOftimesTOExecute 变量吗?
  • 可以创建一个“服务加载器”。查看此问题的答案:stackoverflow.com/questions/45593426/…
【解决方案5】:

你不能从xml中做到这一点,但可以通过在TestNG中使用@DataProvider注解来实现。

这是一个示例代码:

/* Since Data provider for this test method returns 2D array of size 3x1, 
this test method will run 3 times **automatically** with 1 parameter every time. */
@Test(dataProvider="URLprovider")
private void notePrice(String url) {
    driver.get(url);
    System.out.println(driver.getTitle());  
}

// It will return a 2D array of size 3x1
@DataProvider(name="URLprovider")
private Object[][] getURLs() {
  return new Object[][] {
    {"https://www.google.co.in/"},
    {"http://www.gmail.com/"},
    {"http://stackoverflow.com/"}
  };
}

【讨论】:

    【解决方案6】:

    您可以在 testngSuite 中添加多个测试并执行。在所有测试中,类名应该相同,以便多次执行相同的脚本。

    【讨论】:

      【解决方案7】:
      public class ProcessTest implements ITest {
      
      
          protected ProcessData processData;
      
          @Test
          public void executeServiceTest() {
              System.out.println(this.processData.toString());
          }
      
          @Factory(dataProvider = "processDataList")
          public RiskServiceTest(ProcessData processData) {
              this.processData = processData;
          }
      
          @DataProvider(name = "processDataList", parallel=true)
          public static Object[] getProcessDataList() {
      
              Object[] serviceProcessDataList = new Object[10];
      
          for(int i=0; i<=serviceProcessDataList.length; i++){
              ProcessData processData = new ProcessData();
              serviceProcessDataList[i] = processData
          }
      
      
              return serviceProcessDataList;
          }
      
          @Override
          public String getTestName() {
      
              return this.processData.getName();
          }
      }
      

      通过使用 TestNG 的 @Factory 和 @DataProvider 注解,您可以使用不同的数据多次执行相同的测试用例。

      【讨论】:

        【解决方案8】:

        如果你不介意使用 Sprint,你可以创建这个类:

        package somePackage;
        
        import org.junit.Ignore;
        import org.junit.runner.Description;
        import org.junit.runner.notification.RunNotifier;
        import org.junit.runners.BlockJUnit4ClassRunner;
        import org.junit.runners.model.FrameworkMethod;
        import org.junit.runners.model.InitializationError;
        import org.junit.runners.model.Statement;
        import org.springframework.test.annotation.Repeat;
        
        public class ExtendedRunner extends BlockJUnit4ClassRunner {
        
            public ExtendedRunner(Class<?> klass) throws InitializationError {
                super(klass);
            }
        
            @Override
            protected Description describeChild(FrameworkMethod method) {
                if (method.getAnnotation(Repeat.class) != null
                        && method.getAnnotation(Ignore.class) == null) {
                    return describeRepeatTest(method);
                }
                return super.describeChild(method);
            }
        
            private Description describeRepeatTest(FrameworkMethod method) {
                int times = method.getAnnotation(Repeat.class).value();
        
                Description description = Description.createSuiteDescription(
                    testName(method) + " [" + times + " times]",
                    method.getAnnotations());
        
                for (int i = 1; i <= times; i++) {
                    description.addChild(Description.createTestDescription(
                        getTestClass().getJavaClass(), "[" + i + "] "
                                + testName(method)));
                }
                return description;
            }
        
            @Override
            protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
                Description description = describeChild(method);
        
                if (method.getAnnotation(Repeat.class) != null
                        && method.getAnnotation(Ignore.class) == null) {
                    runRepeatedly(methodBlock(method), description, notifier);
                }
                super.runChild(method, notifier);
            }
        
            private void runRepeatedly(Statement statement, Description description,
                    RunNotifier notifier) {
                for (Description desc : description.getChildren()) {
                    runLeaf(statement, desc, notifier);
                }
            }
        
        }
        

        然后在实际测试中:

        package somePackage;
        
        import *.ExtendedRunner;
        
        import org.junit.Ignore;
        import org.junit.runner.RunWith;
        import org.springframework.test.annotation.Repeat;
        
        @Ignore
        @RunWith(ExtendedRunner.class)
        public class RepeatedTest{
            @Repeat(value N)
            public void testToBeRepeated() {
        
            }
        }
        

        其中 N 是您希望测试重复的次数。

        【讨论】:

        • 我正在使用 testng 和数据提供者。我该怎么办?现在我操纵对象数组的大小。你认为这是个好主意吗?
        • 我认为你的意思是“如果你不介意使用 Spring....” 另请注意,这是一个关于 TestNG 的问题,而不是 JUnit。
        猜你喜欢
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多