001: // Copyright © 2002-2007 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps;
003:
004: import java.lang.reflect.InvocationTargetException;
005:
006: import org.apache.log4j.Level;
007: import org.apache.log4j.Logger;
008: import org.apache.tools.ant.Location;
009: import org.apache.tools.ant.Target;
010: import org.apache.xerces.xni.XNIException;
011: import org.xml.sax.SAXException;
012:
013: import com.canoo.webtest.engine.StepExecutionException;
014: import com.canoo.webtest.engine.StepFailedException;
015: import com.canoo.webtest.self.ErrorStepStub;
016: import com.canoo.webtest.self.FailStepStub;
017: import com.canoo.webtest.self.TestBlock;
018: import com.canoo.webtest.self.ThrowAssert;
019:
020: /**
021: * Tests for {@link Step}.
022: * @author unknown
023: * @author Marc Guillemot
024: * @author Denis N. Antonioli
025: * @author Paul King
026: */
027: public class StepTest extends BaseStepTestCase {
028: private Step fFailSpec;
029: private Step fErrorSpec;
030:
031: protected void setUp() throws Exception {
032: super .setUp();
033: fFailSpec = new FailStepStub();
034: configureTask(fFailSpec);
035: fErrorSpec = new ErrorStepStub();
036: configureTask(fErrorSpec);
037: }
038:
039: protected Step createStep() {
040: return new StepStub();
041: }
042:
043: public void testGetDescription() {
044: final Step step = getStep();
045: final String prefix = "PRE";
046: final String desc = "desc";
047: final String suffix = "POST";
048: assertEquals("", step.getDescription(prefix, suffix));
049: step.setDescription(desc);
050: assertEquals(prefix + desc + suffix, step.getDescription(
051: prefix, suffix));
052: }
053:
054: /**
055: * Test that expandDynamicProperties just uses what it needs from the properties map
056: * and not the rest allowing tricky use of this map to save (non String) objects
057: * from groovy (or any other script step) for reuse between 2 steps.
058: */
059: public void testExpandDynamicProperties() {
060: final Step step = getStep();
061: step.getWebtestProperties().put("myProp", "something");
062: step.getWebtestProperties().put("myTrickyUseOfProps",
063: new Object());
064: assertEquals("something", step.getProject().replaceProperties(
065: "#{myProp}"));
066: }
067:
068: public void testLifecycle() {
069: assertStatus(getStep(), false, false, false,
070: "before started notification");
071: getStep().notifyStarted();
072: assertStatus(getStep(), true, false, false,
073: "after started notification");
074: getStep().notifyCompleted();
075: assertStatus(getStep(), true, true, false,
076: "after completed notification");
077: getStep().notifySuccess();
078: assertStatus(getStep(), true, true, true,
079: "after success notification");
080: }
081:
082: public void testIsStartCompletedOnFailure() {
083: assertStatus(fFailSpec, false, false, false, "before execute");
084: ThrowAssert.assertThrows(StepFailedException.class,
085: new TestBlock() {
086: public void call() throws Exception {
087: fFailSpec.execute();
088: }
089: });
090: assertStatus(fFailSpec, true, true, false,
091: "after execute with failure");
092: }
093:
094: public void testIsStartCompletedOnError() {
095: assertStatus(fErrorSpec, false, false, false, "before execute");
096: ThrowAssert.assertThrows(StepExecutionException.class,
097: new TestBlock() {
098: public void call() throws Exception {
099: fErrorSpec.execute();
100: }
101: });
102: assertStatus(fErrorSpec, true, true, false,
103: "after execute with error");
104: }
105:
106: public void testWebtestProperties() throws Exception {
107: final String propName = "count";
108: final String propValue = "2";
109:
110: final RevealingStepStub openingStep = new RevealingStepStub();
111: configureStep(openingStep);
112: executeStep(openingStep);
113: openingStep.setWebtestProperty(propName, propValue);
114:
115: assertEquals("empty string", "", openingStep.getProject()
116: .replaceProperties(""));
117: assertNull("null string", openingStep.getProject()
118: .replaceProperties(null));
119:
120: assertEquals("prop only", propValue, openingStep.getProject()
121: .replaceProperties("#{count}"));
122: assertEquals("prop 1", "X" + propValue + "X", openingStep
123: .getProject().replaceProperties("X#{count}X"));
124: assertEquals("prop 2", propValue + propValue, openingStep
125: .getProject().replaceProperties("#{count}#{count}"));
126: assertEquals("no prop", "X", openingStep.getProject()
127: .replaceProperties("X"));
128: }
129:
130: public void testExceptions() {
131: // dummy statements for coverage purposes: test default forms
132: // of exceptions which are catered for but not generally used
133: new StepFailedException("message").toString();
134: new StepExecutionException("message", (Throwable) null)
135: .toString();
136: }
137:
138: public void testHandleUnexpectedException() {
139: checkUnexpectedException(fFailSpec, new StepFailedException(
140: "message", fFailSpec), StepFailedException.class);
141: checkExecutionException(new StepExecutionException("message",
142: (Throwable) null));
143: final Logger log = Logger.getLogger(Step.class.getName());
144: final Level oldlevel = log.getLevel();
145: log.setLevel(Level.FATAL);
146: checkExecutionException(new NullPointerException("message"));
147: log.setLevel(oldlevel);
148: checkExecutionException(new SAXException("message"));
149: checkExecutionException(new XNIException("message",
150: new RuntimeException("Nested")));
151: checkExecutionException(new XNIException("message",
152: new XNIException("message", new RuntimeException(
153: "Double Nested"))));
154: checkExecutionException(new XNIException("message",
155: new InvocationTargetException(new RuntimeException(
156: "Double Nested"))));
157: }
158:
159: private void checkExecutionException(final Exception exception) {
160: checkUnexpectedException(fErrorSpec, exception,
161: StepExecutionException.class);
162: }
163:
164: private static void checkUnexpectedException(final Step step,
165: final Exception exception, final Class throwable) {
166: ThrowAssert.assertThrows(throwable, new TestBlock() {
167: public void call() throws Exception {
168: step.handleException(exception);
169: }
170: });
171: }
172:
173: public void testHandlesThrowableWithNoMessage() {
174: final String message = ThrowAssert.assertThrows(
175: RuntimeException.class, new TestBlock() {
176: public void call() throws Throwable {
177: getStep().handleException(
178: new RuntimeException());
179: }
180: });
181: assertEquals(
182: "Unexpected exception caught: java.lang.RuntimeException",
183: message);
184: }
185:
186: public void testExecute() throws Exception {
187: assertExecute(new StepStub());
188: }
189:
190: public void testDoExecute() throws Exception {
191: assertDoExecute(new StepStub());
192: }
193:
194: private static void assertStatus(final Step step,
195: final boolean started, final boolean completed,
196: final boolean successful, final String when) {
197: assertEquals("isStarted() should be " + started + " " + when,
198: started, step.isStarted());
199: assertEquals("isCompleted() should be " + completed + " "
200: + when, completed, step.isCompleted());
201: assertEquals("isSuccessful() should be " + successful + " "
202: + when, successful, step.isSuccessful());
203: }
204:
205: private void assertExecute(final Step step) {
206: configureStep(step);
207: step.execute();
208: assertTrue(((AbstractStepVerifierStub) step).isVerified());
209: assertTrue(((AbstractStepVerifierStub) step).isExecuted());
210: }
211:
212: private void assertDoExecute(final Step step) throws Exception {
213: configureStep(step);
214: step.verifyParameters();
215: step.doExecute();
216: assertTrue(((AbstractStepVerifierStub) step).isVerified());
217: assertTrue(((AbstractStepVerifierStub) step).isExecuted());
218: }
219:
220: public static class RevealingStepStub extends Step {
221: public void doExecute() {
222: }
223:
224: }
225:
226: private abstract static class AbstractStepVerifierStub extends
227: RevealingStepStub {
228: private boolean fExecuted;
229: private boolean fVerified;
230:
231: public boolean isExecuted() {
232: return fExecuted;
233: }
234:
235: public boolean isVerified() {
236: return fVerified;
237: }
238:
239: public void setExecuted(final boolean executed) {
240: fExecuted = executed;
241: }
242:
243: public void setVerified(final boolean verified) {
244: fVerified = verified;
245: }
246: }
247:
248: private static final class StepStub extends
249: AbstractStepVerifierStub {
250: public void doExecute() {
251: setExecuted(true);
252: }
253:
254: protected void verifyParameters() {
255: setVerified(true);
256: }
257: }
258:
259: public void testClone() throws Exception {
260: getStep().setLocation(new Location("myFile.xml", 15, 34));
261: getStep().setDescription("foo");
262: getStep().setOwningTarget(new Target());
263: getStep().setTaskType("myType");
264: getStep().setTaskName("myTask");
265:
266: final Step clone = (Step) getStep().clone();
267: assertSameAndNotNull(getStep().getDescription(), clone
268: .getDescription());
269: assertSameAndNotNull(getStep().getLocation(), clone
270: .getLocation());
271: assertSameAndNotNull(getStep().getOwningTarget(), clone
272: .getOwningTarget());
273: assertSameAndNotNull(getStep().getProject(), clone.getProject());
274: assertSameAndNotNull(getStep().getTaskType(), clone
275: .getTaskType());
276: assertSameAndNotNull(getStep().getTaskType(), clone
277: .getTaskType());
278:
279: // don't need to duplicate because it can be the share between a step an its clone
280: // but in a first time, just test equals
281: assertEquals(getStep().getParameterDictionary(), clone
282: .getParameterDictionary());
283: }
284:
285: /**
286: * Test that expected object is not null and is the same as actual object.
287: */
288: protected void assertSameAndNotNull(final Object expected,
289: final Object actual) {
290: assertNotNull(expected);
291: assertSame(expected, actual);
292: }
293: }
|