001: // Copyright © 2002-2007 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.control;
003:
004: import java.util.ArrayList;
005: import java.util.Arrays;
006: import java.util.List;
007: import java.util.regex.Matcher;
008: import java.util.regex.Pattern;
009:
010: import org.apache.commons.lang.ClassUtils;
011: import org.apache.tools.ant.BuildException;
012: import org.apache.tools.ant.RuntimeConfigurable;
013: import org.apache.tools.ant.UnknownElement;
014: import org.jaxen.UnresolvableException;
015: import org.jaxen.VariableContext;
016:
017: import com.canoo.webtest.ant.TestStepSequence;
018: import com.canoo.webtest.ant.WebtestTask;
019: import com.canoo.webtest.engine.Configuration;
020: import com.canoo.webtest.engine.Context;
021: import com.canoo.webtest.engine.StepExecutionException;
022: import com.canoo.webtest.self.StepStub;
023: import com.canoo.webtest.self.TestBlock;
024: import com.canoo.webtest.self.ThrowAssert;
025: import com.canoo.webtest.steps.Step;
026:
027: /**
028: * @author Carsten Seibert
029: * @author Marc Guillemot
030: * @author Paul King
031: */
032: public class RepeatStepTest extends BaseWrappedStepTestCase {
033: private static int sInvocationCounter;
034: private RepeatStep fStep;
035:
036: public static class RepeatTestStub extends StepStub {
037: public void doExecute() {
038: sInvocationCounter++;
039: }
040: }
041:
042: protected void setUp() throws Exception {
043: super .setUp();
044: fStep = (RepeatStep) getStep();
045: }
046:
047: protected Step createStep() {
048: return new RepeatStep();
049: }
050:
051: public void testVerifyParameterValid() throws Exception {
052: executeInContext(createSimpleRepeat(2, 0));
053: executeInContext(createSimpleRepeat(2, 1));
054: executeInContext(createSimpleRepeat(0, 0));
055: }
056:
057: public void testZeroCount() throws Exception {
058: sInvocationCounter = 0;
059: executeInContext(createSimpleRepeat(1, 0));
060: assertEquals("Should not have executed step", 0,
061: sInvocationCounter);
062: }
063:
064: public void testVerifyParameterInvalid() {
065: final Throwable e = ThrowAssert.assertThrows("",
066: BuildException.class, new TestBlock() {
067: public void call() throws Exception {
068: executeInContext(createSimpleRepeat(2, -1));
069: }
070: });
071:
072: assertInstanceOf(StepExecutionException.class, e);
073: }
074:
075: public void testStepExansionWithEndCount() throws Exception {
076: checkStepExpansion(new String[] { "0", "0", "0", "1", "1", "1",
077: "2", "2", "2", "3", "3", "3", "4", "4", "4", "5", "5",
078: "5" }, 3, null, "5", null);
079: }
080:
081: public void testStepExansionWithStartAndEndCount() throws Exception {
082: checkStepExpansion(new String[] { "4", "4", "4", "4", "5", "5",
083: "5", "5", "6", "6", "6", "6" }, 4, "4", "6", null);
084: }
085:
086: public void testStepExansionWithStep() throws Exception {
087: checkStepExpansion(new String[] { "4", "4", "6", "6" }, 2, "4",
088: "6", "2");
089: checkStepExpansion(new String[] { "0" }, 1, null, "2", "3");
090: }
091:
092: private void checkStepExpansion(final String[] expectedStepValues,
093: final int stepCount, final String startCount,
094: final String endCount, final String step) throws Exception {
095: final RuntimeConfigurable wrapper = createRepeatStep(stepCount);
096: if (startCount != null) {
097: wrapper.setAttribute("startCount", startCount);
098: }
099: wrapper.setAttribute("endCount", endCount);
100: if (step != null) {
101: wrapper.setAttribute("step", step);
102: }
103: checkStepExpansion(wrapper, expectedStepValues);
104: }
105:
106: public void testStepExpansion() throws Exception {
107: final RuntimeConfigurable wrapper = createSimpleRepeat(2, 2);
108: checkStepExpansion(wrapper, new String[] { "0", "0", "1", "1" });
109: }
110:
111: private void checkStepExpansion(final RuntimeConfigurable wrapper,
112: final String[] expectedValues) throws Exception {
113: // for(Iterator it = wrapper.getSteps().iterator(); it.hasNext();) {
114: // final RepeatTestStub containedStep = (RepeatTestStub) it.next();
115: // containedStep.fCountName = "#{count}";
116: // }
117:
118: sInvocationCounter = 0;
119: executeInContext(wrapper);
120:
121: // for(Iterator it = wrapper.getSteps().iterator(); it.hasNext();) {
122: // final RepeatTestStub containedStep = (RepeatTestStub) it.next();
123: // System.out.print(containedStep.fCountValue + ":");
124: //
125: // }
126: assertEquals("wrong invocation counter", expectedValues.length,
127: sInvocationCounter);
128:
129: /* final List steps = wrapper.getSteps();
130:
131: int i = 0;
132: assertEquals("Wrong number of steps after execution", expectedValues.length, steps.size());
133: for (final Iterator it = steps.iterator(); it.hasNext(); i++) {
134: final Step containedStep = (Step) it.next();
135: if (i > 0) {
136: assertTrue("elements 0 and "+i+" are identical", steps.get(0) != steps.get(i));
137: }
138: assertTrue("Contained step not started", containedStep.isStarted());
139: assertTrue("Contained step not completed", containedStep.isCompleted());
140: assertNotNull(containedStep.getProject());
141: assertEquals("parameter in steps["+i+"] not correctly expanded", expectedValues[i],
142: ((RepeatTestStub) steps.get(i)).fCountValue);
143: }
144: */}
145:
146: /*
147: public void testNestedRepeatInvocation() throws Exception {
148: int countInnerRepeat = 2;
149: int countOuterRepeat = 3;
150:
151:
152: final RepeatStep outerRepeat = (RepeatStep) getStep();
153:
154: outerRepeat.setCount(new Integer(countOuterRepeat));
155: outerRepeat.setCounterName("y");
156: buildContext(outerRepeat);
157:
158: RepeatTestStub step = new RepeatTestStub();
159: step.setProject(outerRepeat.getProject());
160: step.setDescription("step");
161: step.fCountName = "#{x}:#{y}";
162:
163: final RepeatStep innerRepeat = new RepeatStep();
164: innerRepeat.setProject(outerRepeat.getProject());
165: innerRepeat.addStep(step);
166: innerRepeat.setCount(new Integer(countInnerRepeat));
167: innerRepeat.setCounterName("x");
168:
169: outerRepeat.addTask(innerRepeat);
170:
171: sInvocationCounter = 0;
172:
173: executeStep(outerRepeat);
174:
175: // Get the current step objects because they will have changed due to expanding of steps (multiplication)
176: List outerSteps = outerRepeat.getSteps();
177: List lastInnerSteps = ((AbstractStepContainer) outerSteps.get(outerSteps.size() - 1)).getSteps();
178: RepeatTestStub lastStep = (RepeatTestStub) lastInnerSteps.get(lastInnerSteps.size() - 1);
179:
180: assertEquals("wrong number of steps in outer repeat", countOuterRepeat,
181: outerRepeat.getSteps().size());
182: RepeatStep innerWrapper0 = (RepeatStep) outerRepeat.getSteps().get(0);
183: RepeatStep innerWrapper1 = (RepeatStep) outerRepeat.getSteps().get(1);
184:
185: assertTrue("inner[0] and [1] are ==", innerWrapper0 != innerWrapper1);
186: assertEquals("wrong number of steps in inner repeat[0]", countInnerRepeat,
187: innerWrapper0.getSteps().size());
188: assertEquals("wrong number of steps in inner repeat[1]", countInnerRepeat,
189: innerWrapper1.getSteps().size());
190: assertEquals("wrong number of invocations", countInnerRepeat * countOuterRepeat,
191: sInvocationCounter);
192: assertEquals("inner parameter not expanded", "1:2", lastStep.fCountValue);
193: }
194: */
195:
196: public void testRejectsInvalidStepValues() {
197: fStep.setStep(0);
198: assertErrorOnExecute(fStep, "zero step",
199: "Step must be greater than or equal to 1!");
200:
201: }
202:
203: public void testRejectsEndCountBeforeStartCount() {
204: fStep.setStartCount(5);
205: fStep.setEndCount(new Integer(4));
206: assertErrorOnExecute(fStep, "end before start",
207: "endCount (4) must be greater than or equal to startCount (5)!");
208: }
209:
210: public void testCountOrEndCountRequired() {
211: assertErrorOnExecute(fStep, "count or endcount",
212: "You must specify a count, a endCount or a XPath attribute.");
213: }
214:
215: private RuntimeConfigurable createSimpleRepeat(final int stepCount,
216: final int repeatCount) {
217: final RuntimeConfigurable wrapper = createRepeatStep(stepCount);
218: wrapper.setAttribute("count", String.valueOf(repeatCount));
219: return wrapper;
220: }
221:
222: private RuntimeConfigurable createRepeatStep(final int stepCount) {
223: final RuntimeConfigurable repeat = parseStep(RepeatStep.class,
224: "");
225:
226: for (int i = 0; i < stepCount; i++) {
227: final RuntimeConfigurable repeatStub = parseStep(
228: RepeatTestStub.class, "description='step " + i
229: + "'");
230: repeat.addChild(repeatStub);
231: }
232: return repeat;
233: }
234:
235: RuntimeConfigurable parseStep(final Class aClass,
236: final String attributes) {
237: final String tagName = ClassUtils.getShortClassName(aClass);
238: final UnknownElement task = new UnknownElement(tagName);
239: task.setQName(tagName);
240: task.setTaskType(tagName);
241: task.setTaskName(tagName);
242: configureTask(task);
243:
244: getProject().addTaskDefinition(tagName, aClass);
245:
246: final RuntimeConfigurable wrapper = new RuntimeConfigurable(
247: task, task.getTaskName());
248: final Pattern p = Pattern.compile("(\\w+)='([^']*)'");
249:
250: final Matcher m = p.matcher(attributes);
251: while (m.find()) {
252: final String name = m.group(1);
253: final String value = m.group(2);
254: wrapper.setAttribute(name, value);
255: }
256:
257: return wrapper;
258: }
259:
260: private void executeInContext(final RuntimeConfigurable step)
261: throws Exception {
262: buildContext(step);
263: ((UnknownElement) step.getProxy()).perform();
264: }
265:
266: private static void buildContext(
267: final RuntimeConfigurable repeatstep) {
268: final WebtestTask webtest = new WebtestTask();
269: webtest.setName("testDummy");
270:
271: final Configuration testConfig = new Configuration();
272: webtest.addConfig(testConfig);
273: testConfig.setHost("myHost");
274:
275: final TestStepSequence steps = new TestStepSequence();
276: steps.addTask((UnknownElement) repeatstep.getProxy());
277: webtest.addSteps(steps);
278:
279: WebtestTask.setThreadContext(new Context(webtest));
280: }
281:
282: public void testRepeatByXPath() {
283: final List nodes = Arrays.asList(new Object[] { "foo",
284: new Object(), new Integer(1) });
285: final VariableContext variableContext = getContext()
286: .getXPathHelper().getVariableContext();
287:
288: final List actualNodes = new ArrayList();
289: final RepeatStep step = new RepeatStep() {
290: protected List getNodesByXPath() {
291: return nodes;
292: }
293:
294: protected void executeContainedTasks(String _loopLabel) {
295: try {
296: actualNodes.add(variableContext.getVariableValue(
297: null, null, getCounterName()));
298: } catch (final UnresolvableException e) {
299: throw new RuntimeException(e);
300: }
301: }
302: };
303: configureStep(step);
304: step.setXpath("/my/xpath/selecting/some/nodes");
305:
306: step.execute();
307: assertEquals(nodes, actualNodes);
308: }
309: }
|