9.TestNG依赖测试

Posted by Shen's Blog on Tuesday, December 6, 2022

TestNG依赖测试

有时,我们可能需要以特定顺序调用测试用例中的方法,或者可能希望在方法之间共享一些数据和状态。 TestNG支持这种依赖关系,因为它支持在测试方法之间显式依赖的声明。

TestNG允许指定依赖关系:

  • 在@Test注释中使用属性dependsOnMethods
  • 在@Test注释中使用属性dependsOnGroups。

在TestNG中,我们使用dependOnMethods和dependsOnGroups来实现依赖测试。 如果依赖方法失败,则将跳过所有后续测试方法。

1.dependOnMethods示例

一个简单的例子,“method2()”依赖于“method1()”。

1.1. 如果method1()通过,那么将执行method2()。

App.java


import org.testng.annotations.Test;

public class App {

    @Test
    public void method1() {
        System.out.println("This is method 1");
    }

    @Test(dependsOnMethods = { "method1" })
    public void method2() {
        System.out.println("This is method 2");
    }

}

运行日志:

This is method 1
This is method 2

===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

1.2. 如果method1()失败,则将跳过method2()。

App2.java


import org.testng.annotations.Test;

public class App2 {

    // This test will be failed.
    @Test
    public void method1() {
        System.out.println("This is method 1");
        throw new RuntimeException();
    }

    @Test(dependsOnMethods = { "method1" })
    public void method2() {
        System.out.println("This is method 2");
    }

}

日志如下:


This is method 1

java.lang.RuntimeException
	at com.example.testngenable.depend.App2.method1(App2.java:12)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
	at org.testng.TestRunner.privateRun(TestRunner.java:767)
	at org.testng.TestRunner.run(TestRunner.java:617)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
	at org.testng.SuiteRunner.run(SuiteRunner.java:240)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
	at org.testng.TestNG.run(TestNG.java:1057)
	at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
	at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)


测试已忽略.

===============================================
Default Suite
Total tests run: 2, Failures: 1, Skips: 1
===============================================

2. dependsOnGroups示例

下面我们创建几个测试用例来证明dependsOnMethods和dependsOnGroups的混合使用。 代码比较简单,参阅下面注释就能明白了。

TestService.java

import org.testng.annotations.Test;

//all methods of this class are belong to "deploy" group.
@Test(groups = "deploy")
public class TestServer {

    @Test
    public void deployServer() {
        System.out.println("Deploying Server...");
    }

    // Run this if deployServer() is passed.
    @Test(dependsOnMethods = "deployServer")
    public void deployBackUpServer() {
        System.out.println("Deploying Backup Server...");
    }

}

TestDatabase.java

import org.testng.annotations.Test;

public class TestDatabase {

    //belong to "db" group,
    //Run if all methods from "deploy" group are passed.
    @Test(groups="db", dependsOnGroups="deploy")
    public void initDB() {
        System.out.println("This is initDB()");
    }

    //belong to "db" group,
    //Run if "initDB" method is passed.
    @Test(dependsOnMethods = { "initDB" }, groups="db")
    public void testConnection() {
        System.out.println("This is testConnection()");
    }

}

TestApp.java

import org.testng.annotations.Test;

public class TestApp {

    //Run if all methods from "deploy" and "db" groups are passed.
    @Test(dependsOnGroups={"deploy","db"})
    public void method1() {
        System.out.println("This is method 1");
        //throw new RuntimeException();
    }

    //Run if method1() is passed.
    @Test(dependsOnMethods = { "method1" })
    public void method2() {
        System.out.println("This is method 2");
    }

}

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestDependency">

    <test name="TestCase1">

        <classes>
            <class
                    name="com.example.testngenable.depend.TestApp">
            </class>
            <class
                    name="com.example.testngenable.depend.TestDatabase">
            </class>
            <class
                    name="com.example.testngenable.depend.TestServer">
            </class>
        </classes>SELECT COUNT(1)
FROM (
  SELECT adr.id, adr.corp_id, adr.discount_bank_name, adr.discount_bank_account, adr.discount_bank_no
    , adr.jd_discount_order_no, adr.liquidation_type, adr.collection_account, adr.draft_no, adr.draft_amt
    , adr.acceptance, adr.annual_interest, adr.expiry_date, adr.discount_amt, adr.bank_code
    , adr.create_date
    , CASE 
      WHEN adr.direct_type = 0 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN adr.update_date
          ELSE NULL
        END
      WHEN adr.direct_type = 2 THEN 
        CASE 
          WHEN adr.trade_status = 1 THEN adr.update_date
          ELSE NULL
        END
      ELSE 1
    END AS update_date, adr.bank_channel_type, adr.cert_no
    , CASE 
      WHEN adr.direct_type = 0 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN 2
          WHEN adr.trade_status = 30 THEN 3
          WHEN adr.trade_status = 21 THEN 4
          ELSE 1
        END
      WHEN adr.direct_type = 2 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN 1
          WHEN adr.trade_status = 1 THEN 2
          WHEN adr.trade_status = 2 THEN 3
          WHEN adr.trade_status = 3 THEN 4
          ELSE 1
        END
      ELSE 1
    END AS trade_status, adr.direct_type, adr.endorse_desc, adr.draft_url, adr.enterprise_code
    , CASE 
      WHEN adr.enterprise_code = 'sdpj' THEN '深度票据网'
      ELSE (
        SELECT name
        FROM domain_info di
        WHERE di.enterprise_code = adr.enterprise_code
        LIMIT 1
      )
    END AS enterprise_code_name, adr.tips_msg, sc.corp_name
  FROM adds_discount_record adr
    LEFT JOIN sd_corp sc ON sc.id = adr.corp_id
  WHERE 1 = 1
    AND CASE 
      WHEN adr.direct_type = 0 THEN adr.trade_status = 0
      WHEN adr.direct_type = 2 THEN adr.trade_status = 1
    END
    AND (adr.corp_id, adr.enterprise_code) IN (
      SELECT corp_id, enterprise_code
      FROM discount_staff
      WHERE staff_type = 1
        AND new_staff_id = '1415970510481133570'
    )
    AND (adr.corp_id, adr.enterprise_code) IN (
      SELECT corp_id, enterprise_code
      FROM discount_staff
      WHERE staff_type = 1
        AND new_staff_id = '1415970510481133570'
    )
  ORDER BY adr.create_date DESC
) TOTAL  SELECT COUNT(1)
FROM (
  SELECT adr.id, adr.corp_id, adr.discount_bank_name, adr.discount_bank_account, adr.discount_bank_no
    , adr.jd_discount_order_no, adr.liquidation_type, adr.collection_account, adr.draft_no, adr.draft_amt
    , adr.acceptance, adr.annual_interest, adr.expiry_date, adr.discount_amt, adr.bank_code
    , adr.create_date
    , CASE 
      WHEN adr.direct_type = 0 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN adr.update_date
          ELSE NULL
        END
      WHEN adr.direct_type = 2 THEN 
        CASE 
          WHEN adr.trade_status = 1 THEN adr.update_date
          ELSE NULL
        END
      ELSE 1
    END AS update_date, adr.bank_channel_type, adr.cert_no
    , CASE 
      WHEN adr.direct_type = 0 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN 2
          WHEN adr.trade_status = 30 THEN 3
          WHEN adr.trade_status = 21 THEN 4
          ELSE 1
        END
      WHEN adr.direct_type = 2 THEN 
        CASE 
          WHEN adr.trade_status = 0 THEN 1
          WHEN adr.trade_status = 1 THEN 2
          WHEN adr.trade_status = 2 THEN 3
          WHEN adr.trade_status = 3 THEN 4
          ELSE 1
        END
      ELSE 1
    END AS trade_status, adr.direct_type, adr.endorse_desc, adr.draft_url, adr.enterprise_code
    , CASE 
      WHEN adr.enterprise_code = 'sdpj' THEN '深度票据网'
      ELSE (
        SELECT name
        FROM domain_info di
        WHERE di.enterprise_code = adr.enterprise_code
        LIMIT 1
      )
    END AS enterprise_code_name, adr.tips_msg, sc.corp_name
  FROM adds_discount_record adr
    LEFT JOIN sd_corp sc ON sc.id = adr.corp_id
  WHERE 1 = 1
    AND CASE 
      WHEN adr.direct_type = 0 THEN adr.trade_status = 0
      WHEN adr.direct_type = 2 THEN adr.trade_status = 1
    END
    AND (adr.corp_id, adr.enterprise_code) IN (
      SELECT corp_id, enterprise_code
      FROM discount_staff
      WHERE staff_type = 1
        AND new_staff_id = '1415970510481133570'
    )
    AND (adr.corp_id, adr.enterprise_code) IN (
      SELECT corp_id, enterprise_code
      FROM discount_staff
      WHERE staff_type = 1
        AND new_staff_id = '1415970510481133570'
    )
  ORDER BY adr.create_date DESC
) TOTAL  

    </test>

</suite>

运行结果如下:

Deploying Server...
Deploying Backup Server...
This is initDB()
This is testConnection()
This is method 1
This is method 2

===============================================
TestDependency
Total tests run: 6, Failures: 0, Skips: 0
===============================================

解读:

1.套件测试,测试用例1:测试TsesApp、测试TestDatabase、测试TestService。 2.TestApp: 依赖deplay组和db组,db组、所以先运行这两个组,然后运行TestApp。 3.TestDatabase:已经运行过,所以不需要再运行。 4.TestService:同理,不再运行。