• TestNG并发执行用例详解和范例


     

    前言

    TestNG有多种并发方式支持,方法的并发,class级的并发,test级的并发等;
    根据实际应用可以灵活的配置和使用,下面分别对几种并发方法进行说明:

    一、方法级并发

    方法级并发即method级并发,此种并发方式需要将xml中的suite标签的parallel属性设置为methods并添加属性thread-count并设置其值,其会将所有的方法按照设定的并发数进行并发,譬如总共有4个测试用例,并发数设置为3,则会开三个线程,那么必然会有两个用例是在同一个线程内的,跟用例在哪个class内没关系,范例如下:
    测试用例类一ThreadTest.java

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-2 thread id:"+id);
    	}
    }
    

    测试用例类二ThreadTest2

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest2 {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-2 thread id:"+id);
    	}
    }
    
    

    xml设置并发数为3,并发类型为methods

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="threadSuite" parallel="methods" thread-count="3">
      <test name="Test">
        <classes>
          <class name="com.demo.test.testng.ThreadTest"/>
          <class name="com.demo.test.testng.ThreadTest2"/>
        </classes>
      </test> <!-- Test -->
    </suite> <!-- Suite -->
    

    执行结果如下:

    [RemoteTestNG] detected TestNG version 6.10.0
    [TestNG] Running:
      D:softwareworkspace	estngsrcmainjavacomdemo	est	estCaseThreadTestXml.xml
    
    test1-1 thread id:12
    test2-1 thread id:14
    test1-2 thread id:13
    test2-2 thread id:13
    
    ===============================================
    threadSuite
    Total tests run: 4, Failures: 0, Skips: 0
    ===============================================
    

    如上图所示,确实是开了三个线程,且有两个相同线程号的用例并非同一个测试类;

    二、class级并发

    此并发方式需要将xml中的suite标签内的属性parallel属性设置为classes,且添加属性thread-count并设置其值即可实现class级别并发,其会一个class内的所有方法放在一个线程内,根据线程数设置和总的class数来分配线程,譬如如果设置线程数为3,而class数目为2,则会开两个线程来分别运行两个class,而如果设置线程数为3,且class数目为4则将会有两个class在一个线程内,如下为一个简单的范例:
    两个用例类如下:
    ThreadTest.java

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-2 thread id:"+id);
    	}
    }
    
    

    ThreadTest2.java

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest2 {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-2 thread id:"+id);
    	}
    }
    
    

    测试xml如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="threadSuite" parallel="classes" thread-count="3" verbose="2">
      <test name="Test">
        <classes>
          <class name="com.demo.test.testng.ThreadTest"/>
          <class name="com.demo.test.testng.ThreadTest2"/>
        </classes>
      </test> <!-- Test -->
    </suite> <!-- Suite -->
    

    运行结果:

    [RemoteTestNG] detected TestNG version 6.10.0
    ...
    ... TestNG 6.10 by Cédric Beust (cedric@beust.com)
    ...
    
    [TestNG] Running:
      D:softwareworkspace	estngsrcmainjavacomdemo	est	estCaseThreadTestXml.xml
    
    [TestRunner] Starting executor for test Test with time out:2147483647 milliseconds.
    test2-1 thread id:13
    test1-1 thread id:12
    test2-2 thread id:13
    test1-2 thread id:12
    PASSED: test1
    PASSED: test1
    PASSED: test2
    PASSED: test2
    
    ===============================================
        Test
        Tests run: 4, Failures: 0, Skips: 0
    ===============================================
    

    可以看到两个类分别开了一个线程,同一个类中的用例在同一个线程内,符合预期;
    那么如果有一个suite下有多个test,这个并发设置会否将所有的test都计算在呢?来试一下,新添加一个测试用例Depend1.java

    package com.demo.test.testng;
    
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    
    public class DependTest1 {
    	
    	@Test(groups= {"dependGroup1"})
    	public void dependTest1() 
    	{
    		System.out.println("dependTest1");
    	}
    	
    	@Test(groups= {"dependGroup1"})
    	public void dependTest2() 
    	{
    		System.out.println("dependTest2");
    	}
    	
    	@Test(groups="dependGroup2")
    	public void dependTest4() 
    	{
    		System.out.println("dependTest4");
    		Assert.assertFalse(false);
    	}
    }
    
    

    修改xml为如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="threadSuite" parallel="classes" thread-count="2" verbose="2">
      <test name="Test1">
        <classes>
          <class name="com.demo.test.testng.ThreadTest"/>
          <class name="com.demo.test.testng.ThreadTest2"/>
        </classes>
      </test> <!-- Test -->
      <test name="test2">
        <classes>
          <class name="com.demo.test.testng.DependTest1">
        </class></classes>
      </test>
    </suite> <!-- Suite -->
    

    再次运行结果如下:

    [RemoteTestNG] detected TestNG version 6.10.0
    ...
    ... TestNG 6.10 by Cédric Beust (cedric@beust.com)
    ...
    
    [TestNG] Running:
      D:softwareworkspace	estngsrcmainjavacomdemo	est	estCaseThreadTestXml.xml
    
    [TestRunner] Starting executor for test Test1 with time out:2147483647 milliseconds.
    test2-1 thread id:13
    test1-1 thread id:12
    test2-2 thread id:13
    test1-2 thread id:12
    PASSED: test1
    PASSED: test1
    PASSED: test2
    PASSED: test2
    
    ===============================================
        Test1
        Tests run: 4, Failures: 0, Skips: 0
    ===============================================
    
    [TestRunner] Starting executor for test test2 with time out:2147483647 milliseconds.
    dependTest1
    dependTest2
    dependTest4
    PASSED: dependTest1
    PASSED: dependTest2
    PASSED: dependTest4
    
    ===============================================
        test2
        Tests run: 3, Failures: 0, Skips: 0
    ===============================================
    
    
    ===============================================
    threadSuite
    Total tests run: 7, Failures: 0, Skips: 0
    ===============================================
    

    可以看到是先运行test1(内含两个测试类),开了两个线程,而后再运行test2(内含一个测试类),开了一个线程,而这两个test内的三个class是并没有放在一起运行的;
    故这种并发设置是根据每个test标签生效的;

    三、test级并发

    test级并发为将xml中每个test标签下的用例放在一个线程内并根据并发数和tet数目开线程的并发方法,需要将xml中的suite标签内的属性parallel属性设置为tests,且添加属性thread-count并设置其值即可,譬如有一个suite下有两个test且并发数设置为2,那么就会开两个线程,每个线程都包含一个test,范例如下:
    ThreadTest.java:

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-2 thread id:"+id);
    	}
    }
    
    

    ThreadTest2.java

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest2 {
    	
    	@Test()
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test2-2 thread id:"+id);
    	}
    }
    

    修改DependTest1.java:

    package com.demo.test.testng;
    
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    
    public class DependTest1 {
    	
    	@Test(groups= {"dependGroup1"})
    	public void dependTest1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("dependTest1 id:"+id);
    	}
    	
    	@Test(groups= {"dependGroup1"})
    	public void dependTest2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("dependTest2 id:"+id);
    	}
    	
    	@Test(groups="dependGroup2")
    	public void dependTest4() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("dependTest4 id:"+id);
    		Assert.assertFalse(false);
    	}
    }
    
    

    xml设置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="threadSuite" parallel="tests" thread-count="2" verbose="2">
      <test name="Test1">
        <classes>
          <class name="com.demo.test.testng.ThreadTest"/>
          <class name="com.demo.test.testng.ThreadTest2"/>
        </classes>
      </test> <!-- Test -->
      <test name="test2">
        <classes>
          <class name="com.demo.test.testng.DependTest1">
        </class></classes>
      </test>
    </suite> <!-- Suite -->
    

    运行结果:

    [RemoteTestNG] detected TestNG version 6.10.0
    ...
    ... TestNG 6.10 by Cédric Beust (cedric@beust.com)
    ...
    
    [TestNG] Running:
      D:softwareworkspace	estngsrcmainjavacomdemo	est	estCaseThreadTestXml.xml
    
    [ThreadUtil] Starting executor timeOut:2147483647ms workers:2 threadPoolSize:2
    dependTest1 id:13
    test1-1 thread id:12
    test1-2 thread id:12
    dependTest2 id:13
    test2-1 thread id:12
    dependTest4 id:13
    test2-2 thread id:12
    PASSED: test1
    PASSED: test2
    PASSED: test1
    PASSED: test2
    
    ===============================================
        Test1
        Tests run: 4, Failures: 0, Skips: 0
    ===============================================
    
    PASSED: dependTest1
    PASSED: dependTest2
    PASSED: dependTest4
    
    ===============================================
        test2
        Tests run: 3, Failures: 0, Skips: 0
    ===============================================
    
    
    ===============================================
    threadSuite
    Total tests run: 7, Failures: 0, Skips: 0
    ===============================================
    

    可见两个test是开了两个线程运行的,且同一个test内的用例都在同一个线程内;

    四、instances级并发

    此并发方法与前面几种并发方法类似,只是需要修改parallelinstances即可,为一个实例一个并发,范例如下:

    package com.demo.test.testng;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.testng.annotations.Factory;
    import org.testng.annotations.Test;
    
    public class FactoryTest {
    
    	private String host;
    	private int port;
    	
    	public FactoryTest(String host, int port) 
    	{
    		this.host=host;
    		this.port=port;
    	}
    	
        @Test
        public void login() 
        {
        	long id = Thread.currentThread().getId();
        	System.out.println("login, host:"+host+";port"+port+";id:"+id);
        }
        
        @Test(dependsOnMethods="login")
        public void logout() 
        {
        	long id = Thread.currentThread().getId();
        	System.out.println("logout, host:"+host+";port"+port+";id:"+id);
        }
        
        @Factory
        public static Object[] create() 
        {
        	List<FactoryTest> list = new ArrayList<FactoryTest>();
        	list.add(new FactoryTest("10.10.10.1", 8080));
        	list.add(new FactoryTest("10.10.10.2", 8080));
        	return list.toArray();
        }
    }
    
    

    xml如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="threadSuite" parallel="instances" thread-count="4" verbose="2">
      <test name="Test1">
        <classes>
          <class name="com.demo.test.testng.FactoryTest" />
        </classes>
      </test>
    </suite> <!-- Suite -->
    

    运行结果如下:

    [RemoteTestNG] detected TestNG version 6.10.0
    ...
    ... TestNG 6.10 by Cédric Beust (cedric@beust.com)
    ...
    
    [TestNG] Running:
      D:softwareworkspace	estngsrcmainjavacomdemo	est	estCaseThreadTestXml.xml
    
    [TestRunner] Starting executor for test Test1 with time out:2147483647 milliseconds.
    login, host:10.10.10.1;port8080;id:12
    login, host:10.10.10.2;port8080;id:13
    logout, host:10.10.10.1;port8080;id:14
    logout, host:10.10.10.2;port8080;id:15
    PASSED: login
    PASSED: login
    PASSED: logout
    PASSED: logout
    
    ===============================================
        Test1
        Tests run: 4, Failures: 0, Skips: 0
    ===============================================
    
    
    ===============================================
    threadSuite
    Total tests run: 4, Failures: 0, Skips: 0
    ===============================================
    
    

    如上log可知,两个用例,两组参数,共四条用例开了四个线程,每个用例都是一个实例;
    如果是没有@Factory注解的普通用例,则没效果。

    五、测试用例级并发

    此级并发可以直接在用例内设置,如下为一个范例:

    package com.demo.test.testng;
    
    import org.testng.annotations.Test;
    
    public class ThreadTest {
    	
    	@Test(threadPoolSize = 3, invocationCount = 6, timeOut = 1000)
    	public void test1() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-1 thread id:"+id);
    	}
    
    	@Test
    	public void test2() 
    	{
    		long id = Thread.currentThread().getId();
    		System.out.println("test1-2 thread id:"+id);
    	}
    }
    

    如上图代码所示,test1设置线程数为3,调用次数为6,超时时间为1000ms,运行结果如下:

    [RemoteTestNG] detected TestNG version 6.10.0
    [TestNG] Running:
      C:UsersdufeiAppDataLocalTemp	estng-eclipse--1263110808	estng-customsuite.xml
    
    [ThreadUtil] Starting executor timeOut:1000ms workers:6 threadPoolSize:3
    test1-1 thread id:13
    test1-1 thread id:14
    test1-1 thread id:12
    test1-1 thread id:14
    test1-1 thread id:13
    test1-1 thread id:12
    test1-2 thread id:1
    PASSED: test1
    PASSED: test1
    PASSED: test1
    PASSED: test1
    PASSED: test1
    PASSED: test1
    PASSED: test2
    
    ===============================================
        Default test
        Tests run: 7, Failures: 0, Skips: 0
    ===============================================
    
    
    ===============================================
    Default suite
    Total tests run: 7, Failures: 0, Skips: 0
    ===============================================
    
    [TestNG] Time taken by org.uncommons.reportng.HTMLReporter@1d371b2d: 48 ms
    

    如上所示,test1为三个线程,调用六次,超时为1000ms,符合预期;

  • 相关阅读:
    select应用于read函数 超时非阻塞方式
    取文本索引所执向的值(简单)
    linux c函数指针的应用
    解决vsftp无法启动问题(转)
    Could not chdir to home directory /home/USER: Permission denied
    sscanf和正则表达式
    存储过程重置SEQUENCE值从新开始。
    Signal ()函数详细介绍 Linux函数(转)
    linux 环境NTP配置与开机自启动(转)
    linux下iconv()函数的用法(转载并修改)
  • 原文地址:https://www.cnblogs.com/mashuqi/p/10420095.html
Copyright © 2020-2023  润新知