How can I measure the duration of a test class?

1,354 views
Skip to first unread message

Nagesh

unread,
May 12, 2015, 9:43:13 PM5/12/15
to testng...@googlegroups.com
I would like to log the duration, each test class (classes containing methods annotated with @Test) in the suite took to run. While there is a ready solution with ITestResult for getting the start and end time of a test method, I was wondering if there is a way to calculate the duration of a test class.

I tried the solution below, but I am running into an issue, besides not knowing if this will actually work -

@BeforeClass(alwaysRun = true)
public Long beforeClassStartTime() {
return TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis());
}

@AfterClass(alwaysRun = true)
public void afterClassEndTime(ITestClass testClass) {
Long endTime = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis());
Long durationInMinutes = endTime - beforeClassStartTime();
this.logger.log("Duration of the test class: " + testClass.getName() + " is " + durationInMinutes);
}

Here's the error I get -

org.testng.TestNGException:
Method afterClassEndTime requires 1 parameters but 0 were supplied in the @Configuration annotation.
at org.testng.internal.Parameters.checkParameterTypes(Parameters.java:199)
at org.testng.internal.Parameters.createParameters(Parameters.java:135)
at org.testng.internal.Parameters.createParameters(Parameters.java:377)
at org.testng.internal.Parameters.createConfigurationParameters(Parameters.java:87)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:201)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:140)
at org.testng.internal.TestMethodWorker.invokeAfterClassMethods(TestMethodWorker.java:220)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)

Am I not using the @AfterClass correctly?

Thanks and appreciate the help!

Cédric Beust ♔

unread,
May 12, 2015, 11:25:53 PM5/12/15
to testng...@googlegroups.com

Take a look at the list of legal injections:

http://testng.org/doc/documentation-main.html#native-dependency-injection

ITestClass is not one of them. ITestContext should work.


-- 
Cédric


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users...@googlegroups.com.
To post to this group, send email to testng...@googlegroups.com.
Visit this group at http://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

Nagesh

unread,
May 13, 2015, 12:01:10 PM5/13/15
to testng...@googlegroups.com, ced...@beust.com
Thanks Cédric. I used ITestContext and got the following output -

Duration of the test class: org.testng.TestRunner is 0 seconds

It looks like it didn't pick up the name of the test class correctly. Also, the duration isn't correct, because the test method in that class took 55 seconds to complete.

Not sure if putting System.currentTimeMillis() in the @BeforeClass and @AfterClass is the right approach. I think the answer lies in using ITestResult and adding up the times taken by each test method in the class to get the duration of the class. But I'm not sure how I can only add up the durations of the test methods specific to that class and not other test methods that maybe running in parallel. 

Do you have any ideas or suggestions on how I measure test class duration within the framework? 

-Nagesh

吴亭

unread,
May 13, 2015, 4:22:03 PM5/13/15
to testng...@googlegroups.com
Hi,

Maybe you can do it like this:
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;

public class MyParent {

    long start;

    @BeforeClass(alwaysRun = true)
    public void beforeCls() {
        start = System.currentTimeMillis();
    }

    @AfterClass(alwaysRun = true)
    public void afterClass() {
        System.err.println("Duration: " + this.getClass().getName()
                + (System.currentTimeMillis() - start));
    }
}

You can make this part of code in your class.

Log output:
Test bb
Test dd
Test 2
Duration: gg.RegressionClassTwo1039
Test aa
Test 0
Test 1
Duration: gg.SmokeClassOne53

Nagesh

unread,
May 14, 2015, 1:33:58 PM5/14/15
to testng...@googlegroups.com
Hi Tim,

How is this solution different from what I already discussed above? Are you suggesting I put this in every test class in my suite?

-Nagesh

吴亭

unread,
May 14, 2015, 1:56:35 PM5/14/15
to testng...@googlegroups.com
Hi,

No big difference, the concept is similar. You can put it into a parent class, then make your testcase extend it.

And one more thing is that for my way, you dont need consider ITestContext issue.

Br,
Tim

Nagesh

unread,
May 22, 2015, 1:53:46 AM5/22/15
to testng...@googlegroups.com
Hi Tim,

Thanks for your solution. It didn't strike me that I could simply use this.getClass.getName() instead of TestNG injections :). Yeah, I put the @BeforeClass and @AfterClass in the super class that is inherited by other test classes. 

Thanks again!

-Nagesh
Reply all
Reply to author
Forward
0 new messages