1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.testng;
18 
19 import org.testng.TestNG;
20 import org.testng.xml.XmlClass;
21 import org.testng.xml.XmlInclude;
22 import org.testng.xml.XmlSuite;
23 import org.testng.xml.XmlTest;
24 
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * Test runner to run a single TestNG test. It will output either [PASSED] or [FAILED] at the end.
30  */
31 public class SingleTestNGTestRunner {
32     private static String mUsage = "Usage: java -cp <classpath> SingleTestNGTestRunner" +
33             " class#testMethod";
34     private static final String PASSED_TEST_MARKER = "[ PASSED ]";
35     private static final String FAILED_TEST_MARKER = "[ FAILED ]";
36 
main(String... args)37     public static void main(String... args) {
38         if (args.length != 1) {
39             throw new IllegalArgumentException(mUsage);
40         }
41         String[] classAndMethod = args[0].split("#");
42         if (classAndMethod.length != 2) {
43             throw new IllegalArgumentException(mUsage);
44         }
45 
46         TestNG testng = createTestNG(classAndMethod[0], classAndMethod[1]);
47         testng.run();
48         String status = (!testng.hasFailure()) ? PASSED_TEST_MARKER : FAILED_TEST_MARKER;
49         System.out.println(String.format("%s %s.%s", status,
50                 classAndMethod[0], classAndMethod[1]));
51     }
52 
createTestNG(String klass, String method)53     private static org.testng.TestNG createTestNG(String klass, String method) {
54         org.testng.TestNG testng = new org.testng.TestNG();
55         testng.setUseDefaultListeners(false);  // Don't create the testng-specific HTML/XML reports.
56         testng.addListener(new SingleTestNGTestRunListener());
57 
58         /* Construct the following equivalent XML configuration:
59          *
60          * <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
61          * <suite>
62          *   <test>
63          *     <classes>
64          *       <class name="$klass">
65          *         <include name="$method" />
66          *       </class>
67          *     </classes>
68          *   </test>
69          * </suite>
70          *
71          * This will ensure that only a single klass/method is being run by testng.
72          * (It can still be run multiple times due to @DataProvider, with different parameters
73          * each time)
74          */
75         List<XmlSuite> suites = new ArrayList<>();
76         XmlSuite the_suite = new XmlSuite();
77         XmlTest the_test = new XmlTest(the_suite);
78         XmlClass the_class = new XmlClass(klass);
79         XmlInclude the_include = new XmlInclude(method);
80 
81         the_class.getIncludedMethods().add(the_include);
82         the_test.getXmlClasses().add(the_class);
83         suites.add(the_suite);
84         testng.setXmlSuites(suites);
85 
86         return testng;
87     }
88 }
89