Parallelisierte Tests mit jeweils zwei Gruppen in TestNG
29. Oktober 2014 Softwaretest von Eric Kubenka
In meinem Job automatisiere ich funktionale Oberflächentests mit Java. Die Testfälle führe ich mittels des TestNG-Frameworks und Selenium aus. Jeder Testfall ist mittels @Annotation
mindestens einer Testgruppe zugeordnet. Die Testfälle werden parallel mit unterschiedlichen Anwendern ausgeführt, da ein Anwender sich zeitgleich nur ein mal am System anmelden kann.
Parallelisiertes Ausführen von Tests mit jeweils zwei Gruppen
Bei der Ausführung eines parallelisierten Smoketest-Sets bin ich dann jedoch ins Stolpern geraten. Ziel ist es Testfälle auszuführen, welcher der Gruppe Group User A
und der Gruppe Smoketest
zugeordnet sind. Parallel dazu in einem anderen Thread sollen die Testfälle ausgeführt werden, welche der Gruppe Group User B
und der Gruppe Smoketest
zugeordnet sind. Leider lässt sich das nicht so einfach in der suite.xml
definieren, sondern ein eigener Listener muss geschrieben werden.
Lang habe ich versucht es ausschließlich über die suite.xml
-Datei zu regeln, jedoch wurden bei mir die Tests dann nie so ausgeführt wie ich es mir vorgestellt habe. Leider war ich mit den erweiteren TestNG-Funktionen nicht so vertraut, weshalb ich einige Recherchezeit benötigte.
Die Suite.xml
Zuerst möchte ich Euch zeigen, wie genau ich meine Test-Suite definiert habe. Der erste test
-Block soll die Tests ausführen welche der Gruppe Smoketest
und zusätzlich der Gruppe Group User A
zugeordnet sind. Der zweite Block ist das Äquivalent dazu mit Anwender B.
Der wichtige Punkt ist in dieser Suite-Definition das Einbinden des listeners
-Blocks. Hier können zusätzliche Funktionen programmatisch abgefangen werden. ICh selbst rufe hier den eigens geschriebenen TestGroupInterceptorListener
auf.
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Smoketest - Parallel Tests" verbose="10" configfailurepolicy="continue" parallel="tests" thread-count="2">
<listeners>
<listener class-name="de.codefever.testautomation.test.utils.TestGroupInterceptorListener"/>
</listeners>
<test name="Tests run with group Group User A">
<groups>
<run>
<include name="Group User A"/>
</run>
</groups>
<packages>
<package name="de.codefever.tests.DE.administration"/>
<package name="de.codefever.tests.DE.kontakt"/>
<package name="de.codefever.tests.DE.post"/>
</packages>
</test>
<test name="Tests run with group Group User B">
<groups>
<run>
<include name="Group User B"/>
</run>
</groups>
<packages>
<package name="de.codefever.tests.DE.administration"/>
<package name="de.codefever.tests.DE.kontakt"/>
<package name="de.codefever.tests.DE.post"/>
</packages>
</test>
</suite>
Der Listener Code
Folgender Listener überschreibt, beziehungsweise implementiert die intercept
-Methode des Interfaces IMethodInterceptor
. Für jede gefundene Test-Methode mit der Gruppe Group User A
oder Group User B
wird geprüft ob diese Methoden zusätzlich noch der Gruppe Smoketest
angehören. Wenn dies der Fall ist, so wird die gefunde Methode in das Testset aufgenommen.
public class TestGroupInterceptorListener implements IMethodInterceptor {
@Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
// Result List
List<IMethodInstance> result = new ArrayList<IMethodInstance>();
// For each test method that matches teh suite definition, run these
for (IMethodInstance instance : methods) {
List<String> grps = Arrays.asList(instance.getMethod().getConstructorOrMethod().getMethod()
.getAnnotation(Test.class).groups());
// Check if the test has the Group "Smoketest"
if (grps.contains("Smoketest")) {
result.add(instance);
}
}
return result;
}
}