question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

group-by-instances with test dependencies causes instantiation of tests to exponentially slow

See original GitHub issue

I recently ran into an issue where TestNG is taking a really long time graphing the order to run tests in. If I don’t use dependsOnMethods then by 1600 test instances (3200 test methods plus some before/after methods) start to run after a second or so but once I add a single dependsOnMethods declaration my tests take over 5 minutes to get ordered and that’s even before anything is run.

# instances total duration (s)
100 0.4504
200 1.449
300 2.740
400 5.498
500 10.28
600 17.82
700 28.59
800 45.10
900 59.39
1000 81.54
1100 109.56
1600 364.92

As you can tell, the growth rate is exponential. Is there any way to speed up this process?

Here is some test code which demonstrates the issue:

import com.google.common.base.Stopwatch
import org.testng.annotations.*

data class TestInstance(val id: Int) {
    companion object {
        init {
            val stopwatch = Stopwatch.createStarted()
            Runtime.getRuntime().addShutdownHook(Thread(Runnable { println(stopwatch) }))
        }

        @Factory fun instances(): Array<Any> = Array(1600) { id -> TestInstance(id) }
    }

    @BeforeMethod fun beforeMethod() = Unit
    @Test fun something() = Unit
    @Test(dependsOnMethods = arrayOf("something")) fun somethingElse() = Unit
    @AfterMethod fun afterMethod() = Unit
    @AfterSuite fun afterSuite() = Unit
}

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:15 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
Aheisscommented, Feb 19, 2018

Hey Guys,

I have been looking into this issue since it is causing problems with being able to run our full test suite. I found a fix that improves performance significantly when running a suite that contains a large number of classes. When trying to run our full suite which consists of about 700 classes containing a total of 8500 test methods on version 6.14.2 the suite never loads similar to what is described in #1077. As pointed out above the issue appears to be be in MethodHelper#topologicalSort looking even further down it looks like MethodHelper#matchmethod gets bogged down when trying to match a regex when a large array is passed, this is true especially when the matching method is far down in the array. I was able to get around this issue by modifying MethodHelper#topologicalSort to first splitting all the methods into their associated class then adding an additional for loop to iterate through all the classes then using the existing for loop to iterates through all the methods in the class to find the dependeduponmethod.

         //Create Map of classes that contain test methods
	LinkedHashMap<ITestClass, ArrayList<ITestNGMethod>> classMethods =  sortIntoClasses(methods);	
	//
	// Create the graph
	//
	for (Map.Entry<ITestClass, ArrayList<ITestNGMethod>> testClass : classMethods.entrySet()) {
		
		//Changed to sort methods in class instead of all methods
		// for (ITestNGMethod m : methods) {
		
		for (ITestNGMethod m : testClass.getValue()) {
			ITestNGMethod[] testList = testClass.getValue().toArray(new ITestNGMethod[testClass.getValue().size()]);
			
			result.addNode(m);

			List<ITestNGMethod> predecessors = Lists.newArrayList();

			String[] methodsDependedUpon = m.getMethodsDependedUpon();
			String[] groupsDependedUpon = m.getGroupsDependedUpon();

			if (methodsDependedUpon.length > 0) {
				ITestNGMethod[] methodsNamed = MethodHelper.findDependedUponMethods(m, testList);
				for (ITestNGMethod pred : methodsNamed) {
					predecessors.add(pred);
				}
			}

I would like to note that this does NOT fix the performance when creating tests using a @factory. This only improves performance when test are grouped by classes. I am just starting to look into the factory issue and will add any new information if I find it.

Here is the sortIntoClasses method is being used above :

private static LinkedHashMap<ITestClass, ArrayList<ITestNGMethod>> sortIntoClasses(ITestNGMethod[] methods) {
	LinkedHashMap<ITestClass, ArrayList<ITestNGMethod>> result = new LinkedHashMap<>();
	for (ITestNGMethod method : methods) {
		// Extract key
		ITestClass methodClass = method.getTestClass();
		// Class already in map
		if (result.containsKey(methodClass)) {
			ArrayList<ITestNGMethod> methodList = result.get(methodClass);
			methodList.add(method);
			result.put(methodClass, methodList);
		} else {
			ArrayList<ITestNGMethod> methodList = new ArrayList<>();
			methodList.add(method);
			result.put(methodClass, methodList);
		}
	}
	return result;

}
0reactions
krmahadevancommented, Feb 23, 2018

Closing this issue since its been fixed via PR https://github.com/cbeust/testng/pull/1705

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unit testing classes that instantiate other classes
Tests should be executed in isolation of each other not classes under the tests. You will isolate only dependencies which makes tests slow...
Read more >
9 Ways To Make Slow Tests Faster - Semaphore CI
Problem: external dependencies slow down tests and add uncertainty to results. Solution: replace external components with test doubles, stubs, ...
Read more >
How to Think About the "new" Operator with Respect to Unit ...
But the reason why Dependency Injection is so important is that within unit-tests you want to test a small subset of your application....
Read more >
Unit Tests in Source Code - Discussion - Swift Forums
Testing is usually treated as an afterthought due to the boilerplate required and the context switching between the test and source-code files.
Read more >
How to make your sluggish Jest tests go faster - ITNEXT
A step-by-step guide how to improve performance of your slow Jest unit test and make them blazingly fast and delightful again.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found