View Javadoc

1   package com.flexiblewebsolutions.xdriveunit;
2   
3   import java.io.File;
4   import java.io.FileNotFoundException;
5   import java.lang.reflect.Constructor;
6   import java.lang.reflect.InvocationTargetException;
7   import java.lang.reflect.Method;
8   
9   import junit.framework.Test;
10  import junit.framework.TestSuite;
11  
12  import com.flexiblewebsolutions.io.util.FileUtils;
13  import com.flexiblewebsolutions.xml.util.XMLStringParser;
14  
15  /***
16   * Builds a TestSuite based on XML configuration information
17   * 
18   * @author Donavon Buss
19   */
20  class TestSuiteLoader {
21  	private final static String METHOD_TAG = "testmethod";
22  
23  	public final static String DECORATOR_TAG = "decorator";
24  
25  	public final static String ALL_METHODS_TAG = "allmethods";
26  
27  	private File _RunDir = null;
28  
29  	private StringBuffer _TestOptions = null;
30  
31  	private String _ClassName = null;
32  
33  	private String _ThreadName = null;
34  
35  	/***
36  	 * Create a TestSuite using an xml configuration
37  	 * 
38  	 * @param pConfigInfo -
39  	 *            XML configuration information
40  	 * @param pThreadName -
41  	 *            Name of this instance of the test
42  	 * @param pClassName -
43  	 *            Class that contains tests to be run
44  	 * @param pRunDir -
45  	 *            Base directory for running the tests
46  	 * @return TestSuite containing any number of tests
47  	 * @throws FileNotFoundException
48  	 */
49  	public Test buildSuite(StringBuffer pConfigInfo, String pThreadName,
50  			String pClassName, File pRunDir) throws FileNotFoundException {
51  		_RunDir = pRunDir;
52  		_ClassName = pClassName;
53  		_ThreadName = pThreadName;
54  		TestConfigurationLoader configLoader = new TestConfigurationLoader(
55  				pConfigInfo);
56  		// configuration file can have info for multiple classes
57  		String configXML = configLoader.parseConfigurationForClass(pClassName);
58  
59  		FileUtils fu = new FileUtils();
60  
61  		if (configXML != null) {
62  			StringBuffer tcBuffer = new StringBuffer(configXML);
63  			// testOptionsFilename contains different flags that can be set for
64  			// test
65  			String testOptionsFilename = XMLStringParser.getValueForTag(
66  					tcBuffer, "testOptionsFileName");
67  			tcBuffer = null;
68  			if (testOptionsFilename != null
69  					&& (!testOptionsFilename.equals(""))) {
70  				File testOptionsFile = new File(pRunDir, testOptionsFilename);
71  				System.err.println("test file: "
72  						+ testOptionsFile.getAbsolutePath());
73  				if (!testOptionsFile.exists()) {
74  					throw new FileNotFoundException("File "
75  							+ testOptionsFile.getAbsolutePath() + " not found.");
76  				}
77  
78  				_TestOptions = fu.loadXMLFileToString(testOptionsFile);
79  				testOptionsFilename = null;
80  			}
81  		}
82  
83  		TestCollection tc = new TestCollection();
84  
85  		if (configXML != null) {
86  			String entryTag = "tests";
87  			String methodsXML = XMLStringParser.getValueForTag(
88  					new StringBuffer(configXML), entryTag);
89  
90  			parseNestedTests(tc, methodsXML);
91  			methodsXML = null;
92  		}
93  		fu = null;
94  		return (tc.getTest());
95  	}
96  
97  	/***
98  	 * If xml string contains test methods, drill down to get data
99  	 * 
100 	 * @param pSuite
101 	 *            Stores the test data until ready to run
102 	 * @param pXmlString
103 	 *            Configuration information for single test
104 	 */
105 	private void parseNestedTests(TestCollection pSuite, String pXmlString) {
106 		//		 Get all nested tag values
107 		// if tag is decorator, then get all nested tag values
108 		//     then add completed decorator to suite
109 		// if tag is test, add test to suite
110 		String[] nestedTags = XMLStringParser.getAllNestedTags(pXmlString);
111 		for (int i = 0; i < nestedTags.length; i++) {
112 			String thisTag = nestedTags[i];
113 			if (thisTag.startsWith("<test")) {
114 				thisTag = XMLStringParser.getValueForTag(new StringBuffer(
115 						thisTag), "test");
116 			}
117 
118 			Test thisTest = null;
119 			//			String thisTag = nestedTags[i];
120 			if (thisTag.startsWith("<" + METHOD_TAG)) {
121 				try {
122 					thisTest = buildTestFromMethod(new StringBuffer(thisTag));
123 					pSuite.addTest(thisTest);
124 				} catch (FileNotFoundException e) {
125 					System.err.println("TEst omitted");
126 					// TODO Auto-generated catch block
127 					e.printStackTrace();
128 				}
129 
130 			} else if (thisTag.startsWith("<" + ALL_METHODS_TAG)) {
131 				try {
132 					thisTest = buildAllTestsForClass(new StringBuffer(thisTag));
133 					pSuite.addTest(thisTest);
134 				} catch (FileNotFoundException e) {
135 					// TODO Auto-generated catch block
136 					e.printStackTrace();
137 				}
138 
139 			} else if (thisTag.startsWith("<" + DECORATOR_TAG + ">")) {
140 				String decTagVal = XMLStringParser.getValueForTag(
141 						new StringBuffer(thisTag), DECORATOR_TAG);
142 				TestCollection decSuite = new TestCollection();
143 				parseNestedTests(decSuite, decTagVal);
144 				TestDecoratorLoader tdl = new TestDecoratorLoader();
145 				Test newTest = tdl.wrapTestWithDecorator(new StringBuffer(
146 						decTagVal), decSuite.getTest());
147 				pSuite.addTest(newTest);
148 			} else {
149 				System.err.println("ignoring tag: " + thisTag);
150 			}
151 		}
152 	}
153 
154 	/***
155 	 * Load the inputFileName tag from the method xml and load contents to
156 	 * stringbuffer
157 	 * 
158 	 * @param pXMLString
159 	 *            XML string for method definition
160 	 * @return File Contents
161 	 * @throws FileNotFoundException
162 	 *             If filename was supplied but does not exist
163 	 */
164 	private StringBuffer loadInputFile(StringBuffer pXMLString)
165 			throws FileNotFoundException {
166 		FileUtils fu = new FileUtils();
167 		String inputFilename = XMLStringParser.getValueForTag(pXMLString,
168 				"inputFileName");
169 		StringBuffer inputXML = null;
170 		if (inputFilename != null && (!inputFilename.trim().equals(""))) {
171 			File inputFile = new File(_RunDir, inputFilename);
172 			if (!inputFile.exists()) {
173 				throw new FileNotFoundException("File "
174 						+ inputFile.getAbsolutePath() + " not found.");
175 			}
176 			inputXML = fu.loadXMLFileToString(inputFile);
177 		}
178 		inputFilename = null;
179 		return (inputXML);
180 	}
181 
182 	/***
183 	 * Adds all tests from class to suite to be returned.
184 	 * 
185 	 * @param allTestsString
186 	 *            XML string parameter containing alltest data
187 	 * @return TestSuite of tests contained in class
188 	 * @throws FileNotFoundException
189 	 *             If filename was supplied but does not exist
190 	 */
191 	private Test buildAllTestsForClass(StringBuffer allTestsString)
192 			throws FileNotFoundException {
193 		StringBuffer inputXML = loadInputFile(allTestsString);
194 		String testString = XMLStringParser.getValueForTag(allTestsString,
195 				ALL_METHODS_TAG);
196 		String[] excludes = XMLStringParser.getMatchingNestedTags(testString,
197 				"excludemethod");
198 
199 		TestSuite testSuite = new TestSuite();
200 		try {
201 			Class thisClass = Class.forName(_ClassName);
202 			Method[] allmethods = thisClass.getMethods();
203 			for (int i = 0; i < allmethods.length; i++) {
204 				Method thisMethod = allmethods[i];
205 				if (thisMethod.getName().startsWith("test")) {
206 					boolean excluded = false;
207 					if (excludes != null) {
208 						for (int y = 0; y < excludes.length && (!excluded); y++) {
209 							String excludeMethodName = XMLStringParser
210 									.getValueForTag(new StringBuffer(
211 											excludes[y]), "excludemethod");
212 							if (thisMethod.getName().equals(excludeMethodName)) {
213 								excluded = true;
214 							}
215 							excludeMethodName = null;
216 						}
217 					}
218 					if (!excluded) {
219 						Test thisTest = buildTestFromMethod(thisMethod
220 								.getName(), inputXML);
221 						testSuite.addTest(thisTest);
222 					}
223 				}
224 			}
225 		} catch (SecurityException e) {
226 			// TODO Auto-generated catch block
227 			e.printStackTrace();
228 		} catch (ClassNotFoundException e) {
229 			// TODO Auto-generated catch block
230 			e.printStackTrace();
231 		}
232 		return (testSuite);
233 	}
234 
235 	/***
236 	 * Takes in an xml string and builds a test case
237 	 * 
238 	 * @param methodsString
239 	 *            XML Configuration for method
240 	 * @return TestCase object that can be added to the suite.
241 	 * @throws FileNotFoundException
242 	 */
243 	private Test buildTestFromMethod(StringBuffer methodsString)
244 			throws FileNotFoundException {
245 		String methodName = XMLStringParser.getValueForTag(methodsString,
246 				"testmethodname");
247 		StringBuffer inputXML = loadInputFile(methodsString);
248 		return (buildTestFromMethod(methodName, inputXML));
249 	}
250 
251 	/***
252 	 * Uses the method name and test input string to build test
253 	 * 
254 	 * @param methodName
255 	 *            Name of test method in class
256 	 * @param inputXML
257 	 *            Input parameters used by the test.
258 	 * @return Newly created Testcase using parameters.
259 	 */
260 	private Test buildTestFromMethod(String methodName, StringBuffer inputXML) {
261 		Test thisTest = null;
262 		try {
263 			Class thisClass = Class.forName(_ClassName);
264 			Constructor constructor = thisClass.getConstructor(new Class[] {
265 					String.class, StringBuffer.class, StringBuffer.class,
266 					String.class });
267 			thisTest = (Test) constructor.newInstance(new Object[] {
268 					methodName, inputXML, _TestOptions, _ThreadName });
269 		} catch (SecurityException e) {
270 			e.printStackTrace();
271 		} catch (IllegalArgumentException e) {
272 			e.printStackTrace();
273 		} catch (ClassNotFoundException e) {
274 			e.printStackTrace();
275 		} catch (NoSuchMethodException e) {
276 			e.printStackTrace();
277 		} catch (InstantiationException e) {
278 			e.printStackTrace();
279 		} catch (IllegalAccessException e) {
280 			e.printStackTrace();
281 		} catch (InvocationTargetException e) {
282 			e.printStackTrace();
283 		}
284 		// return empty test suite
285 		//TODO throw exception
286 		if (thisTest == null) {
287 			thisTest = new TestSuite();
288 		}
289 		return (thisTest);
290 	}
291 }