Integrate test frameworks

This article demonstrates the way to integrate various test frameworks with JDUT.

For quick example, see Examples.


1. TestNG

You should add dependency of guru.mikelue.jdut:testng before using this module.

1.1. Listeners

There are three listeners could be used:

IInvokedMethodYamlFactoryListener

Default listener for building/cleaning data per-method

ISuiteYamlFactoryListener

Default listener for building/cleaning data per-suite

ITestContextYamlFactoryListener

Default listeners for building/clean data per-test

You may extend the listeners to customize usage of YAML API

Note

Because the TestNG engine applies all of the listeners on a suite, you can override needConductData if you want to use multiple listeners for different test classes.

Note that the @Listeners annotation will apply to your entire suite file, just as if you had specified it in a testng.xml file.
If you want to restrict its scope (for example, only running on the current class),
the code in your listener could first check the test method that’s about to run and decide what to do then

— Offical TestNG Doc

1.1.1. Use IInvokedMethodYamlFactoryListener

Example 1. Single invocation of test method
package guru.mikelue.jdut.testng.example;
@Test(suiteName="TurtleSuite")
@Listeners(IInvokedMethodYamlFactoryListener.class) // (1)
public class TurtleTest {
	public TurtleTest() {}

	@BeforeClass // (2)
	void setupDataSource(ITestContext context)
	{
		YamlFactoryListenerBase.setDataSource(context, DataSourceGetter.get());
	}
	@AfterClass // (3)
	void releaseDataSource(ITestContext context)
	{
		YamlFactoryListenerBase.removeDataSource(context);
	}

	// File: classpath:guru/mikelue/jdut/testng/example
	// 		-> TurtleTest-crawl.yaml
	@Test @JdutResource // (4)
	public void crawl()
	{
		// Executes tested code
		// Assertions ...
	}

}
  1. Put the listener into @Listeners link.

  2. Setup DataSource to ITestContext

  3. Release data source from ITestContext

  4. Loading the file: classpath:guru/mikelue/jdut/testng/example/TurtleTest-crawl.yaml src.

Example 2. With @DataProvider
	// clFile: classpath:guru/mikelue/jdut/testng/example
	// 		-> TurtleTest-sleep.yaml
	@Test(dataProvider="sleep") @JdutResource
	@TestNGConfig(oneTimeOnly=true) // (1) (2)
	public void sleep(int time)
	{
		// Executes tested code
		// Assertions ...
	}
	@DataProvider
	Object[][] sleep()
	{
		return new Object[][] {
			{ 20 }, { 40 }, { 60}, { 80 },
		};
	}
  1. Loading the file: classpath:guru/mikelue/jdut/testng/example/TurtleTest-sleep.yaml src

  2. With @TestNGConfig(oneTimeOnly=true), the data is built before the first test and is clean after the last test.

1.1.2. Use ISuiteYamlFactoryListener

Example 1. Extending ISuiteYamlFactoryListener src
Usage of listeners
package guru.mikelue.jdut.testng.example;
// File: LizardSuite.yaml
@Test(suiteName="LizardSuite") // (1)
@Listeners(LizardTest.LizardSuiteListener.class) // (2)
public class LizardTest {

	@Test
	public void crawl()
	{
		// Executes tested code
		// Assertions ...
	}
}
  1. The suite name LizardSuite would be file name of YAML: classpath:LizardSuite.yaml src

  2. Put the listener into @Listeners link.

Extending of ISuiteYamlFactoryListener
	public static class LizardSuiteListener extends ISuiteYamlFactoryListener {
		 @Override // (1)
         public void onStart(ISuite suite)
         {
             setDataSource(suite, DataSourceGetter.get());
             super.onStart(suite); // (2)
         }
         @Override // (3)
         public void onFinish(ISuite suite)
         {
             super.onFinish(suite); // (4)
             removeDataSource(suite);
         }
	}
  1. In onStart method, put the data source into suite

  2. Don’t forget to call parent’s onStart

  3. In onFinish method, remove the data source from suite

  4. Don’t forget to call parent’s onFinish.

1.1.3. Use ITestContextYamlFactoryListener

Example 2. Extending ITestContextYamlFactoryListener src
Usage of listeners
package guru.mikelue.jdut.testng.example;
// File: classpath:CrocodileTest.yaml
@Test(suiteName="CrocodileSuite", testName="CrocodileTest") // (1)
@Listeners(CrocodileTest.CrocodileSuiteListener.class) // (2)
public class CrocodileTest {

	@Test
	public void crawl()
	{
		// Executes tested code
		// Assertions ...
	}
}
  1. The test name CrocodileTest would be file name of YAML: classpath:CrocodileTest.yaml src

  2. Put the listener into @Listeners link.

Extending of ITestContextYamlFactoryListener
	public static class CrocodileSuiteListener extends ITestContextYamlFactoryListener {
		 @Override // (1)
         public void onStart(ITestContext testContext)
         {
             setDataSource(testContext, DataSourceGetter.get());
             super.onStart(testContext); // (2)
         }
         @Override // (3)
         public void onFinish(ITestContext testContext)
         {
             super.onFinish(testContext); // (4)
             removeDataSource(testContext);
         }
	}
  1. In onStart method, put the data source into test context

  2. Don’t forget to call parent’s onStart

  3. In onFinish method, remove the data source from test context

  4. Don’t forget to call parent’s onFinish.

2. JUnit 5

You should add dependency of guru.mikelue.jdut:junit5 before using this module.

JdutYamlFactory provides out-of-box loading of YAML files by convention.

Example 1. By data source src

You can use buildByDataSource() to initialize a JdutYamlFactory.

package guru.mikelue.jdut.junit5.example;
// File: classpath:guru/mikelue/jdut/junit5/example
// 		-> SproutTest.yaml
@TestInstance(PER_CLASS) @JdutResource // (1)
public class SproutTest {
	public SproutTest() {}

	@RegisterExtension // (2)
	static JdutYamlFactory myDataSourceFactory = JdutYamlFactory.buildByDataSource(
		DataSourceGetter::get
	);

	// File: classpath:guru/mikelue/jdut/junit5/example
	// 		-> SproutTest-grow.yaml
	@Test @JdutResource // (3)
	void grow()
	{
		// 1) Execute tested code
		// 2) Assert the result of database
	}
}
  1. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/SproutTest.yaml src

  2. register factory by data source

  3. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/SproutTest-grow.yaml src.

Example 2. By customized YamlConductorFactory src

You can use buildByFactory() to initialize a JdutYamlFactory.

package guru.mikelue.jdut.junit5.example;
// File: classpath:guru/mikelue/jdut/junit5/example
// 		-> ChokosTest.yaml
@TestInstance(PER_CLASS) @JdutResource // (1)
public class ChokosTest {
	public ChokosTest() {}

	@RegisterExtension // (2)
	static JdutYamlFactory myDataSourceFactory = JdutYamlFactory.buildByFactory(
		() -> YamlConductorFactory.build(DataSourceGetter.get())
	);

	// File: classpath:guru/mikelue/jdut/junit5/example
	// 		-> ChokosTest-grow.yaml
	@Test @JdutResource // (3)
	void grow()
	{
		// 1) Execute tested code
		// 2) Assert the result of database
	}
}
  1. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/ChokosTest.yaml src

  2. register factory by data source

  3. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/ChokosTest-grow.yaml src.

Example 3. By inheritance and @ExtendWith src

You should extend JdutYamlFactory and implement getYamlConductorFactory() method.

class InitYamlFactory extends JdutYamlFactory {
	public InitYamlFactory() {}

	@Override
	public void beforeAll(ExtensionContext context) throws Exception
	{
		// When you override the callback, don't forget to call the parent's implementation
		super.beforeAll(context);
	}

	@Override
	public void afterAll(ExtensionContext context) throws Exception
	{
		// When you override the callback, don't forget to call the parent's implementation
		super.afterAll(context);
	}

	@Override
	protected YamlConductorFactory getYamlConductorFactory(ExtensionContext context, Event event)
	{
		Random r = new Random();
		Supplier<Object> randomSize = () -> r.nextInt(101) + 1;

		// You can customize ConductorConfig
		return YamlConductorFactory.build(
			DataSourceGetter.get(),
			builder -> builder.namedSupplier("random_size", randomSize) // (1)
		);
	}
}
  1. You can customize data generation by JDUT’s YAML configuration

Put the factory in @ExtendWith

package guru.mikelue.jdut.junit5.example;
// File: classpath:guru/mikelue/jdut/junit5/example
// 		-> BroccoliTest.yaml
@TestInstance(PER_CLASS) @ExtendWith(InitYamlFactory.class)
@JdutResource // (1)
public class BroccoliTest {
	public BroccoliTest() {}

	// 	File: classpath:guru/mikelue/jdut/junit5/example
	// 		-> BroccoliTest-grow.yaml
	@Test @JdutResource // (2)
	void grow()
	{
		// 1) Execute tested code
		// 2) Assert the result of database
	}
}
  1. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/BroccoliTest.yaml src

  2. loading the data from yaml file: classpath:guru/mikelue/jdut/junit5/example/BroccoliTest-grow.yaml src.

3. JUnit 4

You should add dependency of guru.mikelue.jdut:junit4 before using this module.

This module supports JUnit4 since version of 4.9.

JdutYamlFactory provides out-of-box loading of YAML files by convention.

Example 1. By @ClassRule src
package guru.mikelue.jdut.junit4.example;
// file: classpath:guru/mikelue/jdut/junit4/example
// 		-> PuhaTest.yaml
@JdutResource // (1)
public class PuhaTest {
	@ClassRule // (2)
	public static TestRule rule = JdutYamlFactory.buildByDataSource(DataSourceGetter::get);

	public PuhaTest() {}

	@Test
	public void grow()
	{
		// Executes tested code
		// Assertions...
	}
}
  1. loading the data from yaml file: classpath:guru/mikelue/jdut/junit4/example/TestPuha-grow.yaml src

  2. put @ClassRule on the JdutYamlFactory object.

Example 2. By rule of method src

The only rule provided by this module is JdutYamlFactory.

You may override buildDuetConductor method to load your own YAML file.

package guru.mikelue.jdut.junit4.example;
public class EggplantTest {
	public EggplantTest() {}

	@Rule // (1)
	public JdutYamlFactory jdutYamlFactoryForMethodLevel = new JdutYamlFactory(DataSourceGetter.get());

	// file: classpath:guru/mikelue/jdut/junit4/example
	// 		-> EggplantTest-grow.yaml
	@Test @JdutResource // (2)
	public void grow()
	{
		// Executes tested code
		// Assertions...
	}
}
  1. put @Rule on the JdutYamlFactory object

  2. loading the data from yaml file: classpath:guru/mikelue/jdut/junit4/example/EggplantTest-grow.yaml src.