1
package org.testng.xml;
5
import java.io.FileWriter;
6
import java.io.IOException;
7
import java.util.ArrayList;
8
import java.util.Collection;
11
import java.util.Properties;
13
import org.testng.internal.AnnotationTypeEnum;
14
import org.testng.log4testng.Logger;
15
import org.testng.reporters.XMLStringBuffer;
18
* Wrapper for real suites and custom configured suites.
19
* Should only be used for integration purposes; creating a custom testng.xml
21
* @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
23
public abstract class LaunchSuite {
24
/** This class's log4testng Logger. */
25
private static final Logger LOGGER = Logger.getLogger(LaunchSuite.class);
27
protected boolean m_temporary;
30
* Constructs a <code>LaunchSuite</code>
32
* @param isTemp the temporary status
34
protected LaunchSuite(boolean isTemp) {
39
* Returns the temporary state.
40
* @return the temporary state.
42
public boolean isTemporary() {
47
* Saves the suite file in the specified directory and returns the file
50
* @param directory the directory where the suite file is to be saved.
51
* @return the file pathname of the saved file.
53
public abstract File save(File directory);
56
* <code>ExistingSuite</code> is a non-temporary LaunchSuite based on an existing
59
public static class ExistingSuite extends LaunchSuite {
62
* The existing suite path (either relative to the project root or an absolute path)
64
private File m_suitePath;
67
* Constructs a <code>ExistingSuite</code> based on an existing file
69
* @param path the path to the existing Launch suite.
71
public ExistingSuite(File path) {
78
* {@inheritDoc} This implementation saves nothing because the suite file already
82
public File save(File directory) {
88
* <code>CustomizedSuite</code> TODO cquezel JavaDoc.
90
private abstract static class CustomizedSuite extends LaunchSuite {
91
protected String m_projectName;
92
protected String m_suiteName;
94
/** The annotation type. May be null. */
95
protected AnnotationTypeEnum m_annotationType;
97
protected Map<String, String> m_parameters;
99
/** The string buffer used to write the XML file. */
100
private XMLStringBuffer m_suiteBuffer;
103
* Constructs a <code>CustomizedSuite</code> TODO cquezel JavaDoc.
108
* @param annotationType
110
private CustomizedSuite(final String projectName,
111
final String className,
112
final Map<String, String> parameters,
113
final String annotationType)
117
m_projectName = projectName;
118
m_suiteName = className;
119
m_parameters = parameters;
120
m_annotationType = annotationType == null ? null : AnnotationTypeEnum.valueOf(annotationType, false);
124
* TODO cquezel JavaDoc
128
protected XMLStringBuffer createContentBuffer() {
129
XMLStringBuffer suiteBuffer = new XMLStringBuffer(""); //$NON-NLS-1$
130
suiteBuffer.setDocType("suite SYSTEM \"" + Parser.TESTNG_DTD_URL + "\"");
132
Properties attrs = new Properties();
133
attrs.setProperty("parallel", XmlSuite.PARALLEL_NONE);
134
attrs.setProperty("name", m_suiteName);
135
suiteBuffer.push("suite", attrs);
137
if (m_parameters != null) {
138
for (Map.Entry<String, String> entry : m_parameters.entrySet()) {
139
Properties paramAttrs = new Properties();
140
paramAttrs.setProperty("name", entry.getKey());
141
paramAttrs.setProperty("value", entry.getValue());
142
suiteBuffer.push("parameter", paramAttrs);
143
suiteBuffer.pop("parameter");
147
initContentBuffer(suiteBuffer);
149
suiteBuffer.pop("suite");
155
* TODO cquezel JavaDoc
159
private XMLStringBuffer getSuiteBuffer() {
160
if (null == m_suiteBuffer) {
161
m_suiteBuffer = createContentBuffer();
164
return m_suiteBuffer;
168
* Initializes the content of the xml string buffer.
170
* @param suiteBuffer the string buffer to initialize.
172
protected abstract void initContentBuffer(XMLStringBuffer suiteBuffer);
175
* {@inheritDoc} This implementation saves the suite to the "temp-testng-customsuite.xml"
176
* file in the specified directory.
179
public File save(File directory) {
180
final File suiteFile = new File(directory, "temp-testng-customsuite.xml");
182
saveSuiteContent(suiteFile, getSuiteBuffer());
188
* Saves the content of the string buffer to the specified file.
190
* @param file the file to write to.
191
* @param content the content to write to the file.
193
protected void saveSuiteContent(final File file, final XMLStringBuffer content) {
196
FileWriter fw = new FileWriter(file);
198
fw.write(content.getStringBuffer().toString());
204
catch (IOException ioe) {
205
// TODO CQ is this normal to swallow exception here
206
LOGGER.error("IO Exception", ioe);
212
* A <code>MethodsSuite</code> is a suite made up of methods.
214
static class MethodsSuite extends CustomizedSuite {
215
protected Collection<String> m_methodNames;
216
protected String m_className;
217
protected int m_logLevel;
220
* Constructs a <code>MethodsSuite</code> TODO cquezel JavaDoc.
226
* @param annotationType (may be null)
229
MethodsSuite(final String projectName,
230
final String className,
231
final Collection<String> methodNames,
232
final Map<String, String> parameters,
233
final String annotationType,
234
final int logLevel) {
235
super(projectName, className, parameters, annotationType);
237
m_className = className;
238
m_methodNames = methodNames;
239
m_logLevel = logLevel;
246
protected void initContentBuffer(XMLStringBuffer suiteBuffer) {
247
Properties testAttrs = new Properties();
248
testAttrs.setProperty("name", m_className);
249
if (m_annotationType != null) {
250
testAttrs.setProperty("annotations", m_annotationType.getName());
252
testAttrs.setProperty("verbose", String.valueOf(m_logLevel));
254
suiteBuffer.push("test", testAttrs);
256
suiteBuffer.push("classes");
258
Properties classAttrs = new Properties();
259
classAttrs.setProperty("name", m_className);
261
if ((null != m_methodNames) && (m_methodNames.size() > 0)) {
262
suiteBuffer.push("class", classAttrs);
264
suiteBuffer.push("methods");
266
for (Object methodName : m_methodNames) {
267
Properties methodAttrs = new Properties();
268
methodAttrs.setProperty("name", (String) methodName);
269
suiteBuffer.addEmptyElement("include", methodAttrs);
272
suiteBuffer.pop("methods");
273
suiteBuffer.pop("class");
276
suiteBuffer.addEmptyElement("class", classAttrs);
278
suiteBuffer.pop("classes");
279
suiteBuffer.pop("test");
283
static class ClassesAndMethodsSuite extends CustomizedSuite {
284
protected Map<String, Collection<String>> m_classes;
285
protected int m_logLevel;
287
ClassesAndMethodsSuite(final String projectName,
288
final Map<String, Collection<String>> classes,
289
final Map<String, String> parameters,
290
final String annotationType,
291
final int logLevel) {
292
super(projectName, "Custom suite", parameters, annotationType);
294
m_logLevel = logLevel;
301
protected void initContentBuffer(XMLStringBuffer suiteBuffer) {
302
Properties testAttrs = new Properties();
303
testAttrs.setProperty("name", m_projectName);
304
if (m_annotationType != null) {
305
testAttrs.setProperty("annotations", m_annotationType.getName());
307
testAttrs.setProperty("verbose", String.valueOf(m_logLevel));
309
suiteBuffer.push("test", testAttrs);
311
suiteBuffer.push("classes");
313
for(Map.Entry<String, Collection<String>> entry : m_classes.entrySet()) {
314
Properties classAttrs = new Properties();
315
classAttrs.setProperty("name", entry.getKey());
317
Collection<String> methodNames= sanitize(entry.getValue());
318
if ((null != methodNames) && (methodNames.size() > 0)) {
319
suiteBuffer.push("class", classAttrs);
321
suiteBuffer.push("methods");
323
for (String methodName : methodNames) {
324
Properties methodAttrs = new Properties();
325
methodAttrs.setProperty("name", methodName);
326
suiteBuffer.addEmptyElement("include", methodAttrs);
329
suiteBuffer.pop("methods");
330
suiteBuffer.pop("class");
333
suiteBuffer.addEmptyElement("class", classAttrs);
336
suiteBuffer.pop("classes");
337
suiteBuffer.pop("test");
340
private Collection<String> sanitize(Collection<String> source) {
341
if(null == source) return null;
343
List<String> result= new ArrayList<String>();
344
for(String name: source) {
345
if(!"".equals(name)) {
355
* <code>ClassListSuite</code> TODO cquezel JavaDoc.
357
static class ClassListSuite extends CustomizedSuite {
358
protected Collection<String> m_packageNames;
359
protected Collection<String> m_classNames;
360
protected Collection<String> m_groupNames;
361
protected int m_logLevel;
363
ClassListSuite(final String projectName,
364
final Collection<String> packageNames,
365
final Collection<String> classNames,
366
final Collection<String> groupNames,
367
final Map<String, String> parameters,
368
final String annotationType,
369
final int logLevel) {
370
super(projectName, "Custom suite", parameters, annotationType);
372
m_packageNames = packageNames;
373
m_classNames = classNames;
374
m_groupNames = groupNames;
375
m_logLevel = logLevel;
382
protected void initContentBuffer(XMLStringBuffer suiteBuffer) {
383
Properties testAttrs = new Properties();
384
testAttrs.setProperty("name", m_projectName);
385
if (m_annotationType != null) {
386
testAttrs.setProperty("annotations", m_annotationType.getName());
388
testAttrs.setProperty("verbose", String.valueOf(m_logLevel));
390
suiteBuffer.push("test", testAttrs);
392
if (null != m_groupNames) {
393
suiteBuffer.push("groups");
394
suiteBuffer.push("run");
396
for (String groupName : m_groupNames) {
397
Properties includeAttrs = new Properties();
398
includeAttrs.setProperty("name", groupName);
399
suiteBuffer.addEmptyElement("include", includeAttrs);
402
suiteBuffer.pop("run");
403
suiteBuffer.pop("groups");
406
// packages belongs to suite according to the latest DTD
407
if ((m_packageNames != null) && (m_packageNames.size() > 0)) {
408
suiteBuffer.push("packages");
410
for (String packageName : m_packageNames) {
411
Properties packageAttrs = new Properties();
412
packageAttrs.setProperty("name", packageName);
413
suiteBuffer.addEmptyElement("package", packageAttrs);
415
suiteBuffer.pop("packages");
418
if ((m_classNames != null) && (m_classNames.size() > 0)) {
419
suiteBuffer.push("classes");
421
for (String className : m_classNames) {
422
Properties classAttrs = new Properties();
423
classAttrs.setProperty("name", className);
424
suiteBuffer.addEmptyElement("class", classAttrs);
427
suiteBuffer.pop("classes");
429
suiteBuffer.pop("test");