// Copyright � 2002-2007 Canoo Engineering AG, Switzerland. package com.canoo.webtest.steps.control; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.namespace.QName; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.RuntimeConfigurable; import org.apache.tools.ant.UnknownElement; import com.canoo.webtest.ant.TestStepSequence; import com.canoo.webtest.ant.WebtestTask; import com.canoo.webtest.engine.Configuration; import com.canoo.webtest.engine.Context; import com.canoo.webtest.engine.StepExecutionException; import com.canoo.webtest.engine.xpath.SimpleXPathVariableResolver; import com.canoo.webtest.self.StepStub; import com.canoo.webtest.self.TestBlock; import com.canoo.webtest.self.ThrowAssert; import com.canoo.webtest.steps.Step; /** * @author Carsten Seibert * @author Marc Guillemot * @author Paul King */ public class RepeatStepTest extends BaseWrappedStepTestCase { private static int sInvocationCounter; private RepeatStep fStep; public static class RepeatTestStub extends StepStub { public void doExecute() { sInvocationCounter++; } } protected void setUp() throws Exception { super.setUp(); fStep = (RepeatStep) getStep(); } protected Step createStep() { return new RepeatStep(); } public void testVerifyParameterValid() throws Exception { executeInContext(createSimpleRepeat(2, 0)); executeInContext(createSimpleRepeat(2, 1)); executeInContext(createSimpleRepeat(0, 0)); } public void testZeroCount() throws Exception { sInvocationCounter = 0; executeInContext(createSimpleRepeat(1, 0)); assertEquals("Should not have executed step", 0, sInvocationCounter); } public void testVerifyParameterInvalid() { final Throwable e = ThrowAssert.assertThrows("", BuildException.class, new TestBlock() { public void call() throws Exception { executeInContext(createSimpleRepeat(2, -1)); } }); assertInstanceOf(StepExecutionException.class, e); } public void testStepExansionWithEndCount() throws Exception { checkStepExpansion(new String[]{"0", "0", "0", "1", "1", "1", "2", "2","2","3","3","3","4","4","4","5","5","5"}, 3, null, "5", null); } public void testStepExansionWithStartAndEndCount() throws Exception { checkStepExpansion(new String[]{"4","4","4","4","5","5","5","5","6","6","6","6"}, 4, "4", "6", null); } public void testStepExansionWithStep() throws Exception { checkStepExpansion(new String[]{"4","4","6","6"}, 2, "4", "6", "2"); checkStepExpansion(new String[]{"0"}, 1, null, "2", "3"); } private void checkStepExpansion(final String[] expectedStepValues, final int stepCount, final String startCount, final String endCount, final String step) throws Exception { final RuntimeConfigurable wrapper = createRepeatStep(stepCount); if (startCount != null) { wrapper.setAttribute("startCount", startCount); } wrapper.setAttribute("endCount", endCount); if (step != null) { wrapper.setAttribute("step", step); } checkStepExpansion(wrapper, expectedStepValues); } public void testStepExpansion() throws Exception { final RuntimeConfigurable wrapper = createSimpleRepeat(2, 2); checkStepExpansion(wrapper, new String[]{ "0", "0", "1", "1"}); } private void checkStepExpansion(final RuntimeConfigurable wrapper, final String[] expectedValues) throws Exception { // for(Iterator it = wrapper.getSteps().iterator(); it.hasNext();) { // final RepeatTestStub containedStep = (RepeatTestStub) it.next(); // containedStep.fCountName = "#{count}"; // } sInvocationCounter = 0; executeInContext(wrapper); // for(Iterator it = wrapper.getSteps().iterator(); it.hasNext();) { // final RepeatTestStub containedStep = (RepeatTestStub) it.next(); // System.out.print(containedStep.fCountValue + ":"); // // } assertEquals("wrong invocation counter", expectedValues.length, sInvocationCounter); /* final List steps = wrapper.getSteps(); int i = 0; assertEquals("Wrong number of steps after execution", expectedValues.length, steps.size()); for (final Iterator it = steps.iterator(); it.hasNext(); i++) { final Step containedStep = (Step) it.next(); if (i > 0) { assertTrue("elements 0 and "+i+" are identical", steps.get(0) != steps.get(i)); } assertTrue("Contained step not started", containedStep.isStarted()); assertTrue("Contained step not completed", containedStep.isCompleted()); assertNotNull(containedStep.getProject()); assertEquals("parameter in steps["+i+"] not correctly expanded", expectedValues[i], ((RepeatTestStub) steps.get(i)).fCountValue); } */ } /* public void testNestedRepeatInvocation() throws Exception { int countInnerRepeat = 2; int countOuterRepeat = 3; final RepeatStep outerRepeat = (RepeatStep) getStep(); outerRepeat.setCount(new Integer(countOuterRepeat)); outerRepeat.setCounterName("y"); buildContext(outerRepeat); RepeatTestStub step = new RepeatTestStub(); step.setProject(outerRepeat.getProject()); step.setDescription("step"); step.fCountName = "#{x}:#{y}"; final RepeatStep innerRepeat = new RepeatStep(); innerRepeat.setProject(outerRepeat.getProject()); innerRepeat.addStep(step); innerRepeat.setCount(new Integer(countInnerRepeat)); innerRepeat.setCounterName("x"); outerRepeat.addTask(innerRepeat); sInvocationCounter = 0; executeStep(outerRepeat); // Get the current step objects because they will have changed due to expanding of steps (multiplication) List outerSteps = outerRepeat.getSteps(); List lastInnerSteps = ((AbstractStepContainer) outerSteps.get(outerSteps.size() - 1)).getSteps(); RepeatTestStub lastStep = (RepeatTestStub) lastInnerSteps.get(lastInnerSteps.size() - 1); assertEquals("wrong number of steps in outer repeat", countOuterRepeat, outerRepeat.getSteps().size()); RepeatStep innerWrapper0 = (RepeatStep) outerRepeat.getSteps().get(0); RepeatStep innerWrapper1 = (RepeatStep) outerRepeat.getSteps().get(1); assertTrue("inner[0] and [1] are ==", innerWrapper0 != innerWrapper1); assertEquals("wrong number of steps in inner repeat[0]", countInnerRepeat, innerWrapper0.getSteps().size()); assertEquals("wrong number of steps in inner repeat[1]", countInnerRepeat, innerWrapper1.getSteps().size()); assertEquals("wrong number of invocations", countInnerRepeat * countOuterRepeat, sInvocationCounter); assertEquals("inner parameter not expanded", "1:2", lastStep.fCountValue); } */ public void testRejectsInvalidStepValues() { fStep.setStep(0); assertErrorOnExecute(fStep, "zero step", "Step must be greater than or equal to 1!"); } public void testRejectsEndCountBeforeStartCount() { fStep.setStartCount(5); fStep.setEndCount(new Integer(4)); assertErrorOnExecute(fStep, "end before start", "endCount (4) must be greater than or equal to startCount (5)!"); } public void testCountOrEndCountRequired() { assertErrorOnExecute(fStep, "count or endcount", "You must specify a count, a endCount or a XPath attribute."); } private RuntimeConfigurable createSimpleRepeat(final int stepCount, final int repeatCount) { final RuntimeConfigurable wrapper = createRepeatStep(stepCount); wrapper.setAttribute("count", String.valueOf(repeatCount)); return wrapper; } private RuntimeConfigurable createRepeatStep(final int stepCount) { final RuntimeConfigurable repeat = parseStep(RepeatStep.class, ""); for (int i = 0; i < stepCount; i++) { final RuntimeConfigurable repeatStub = parseStep(RepeatTestStub.class, "description='step " + i + "'"); repeat.addChild(repeatStub); } return repeat; } private void executeInContext(final RuntimeConfigurable step) throws Exception { buildContext(step); ((UnknownElement) step.getProxy()).perform(); } private static void buildContext(final RuntimeConfigurable repeatstep) { final WebtestTask webtest = new WebtestTask(); webtest.setName("testDummy"); final Configuration testConfig = new Configuration(); webtest.addConfig(testConfig); testConfig.setHost("myHost"); final TestStepSequence steps = new TestStepSequence(); steps.addTask((UnknownElement) repeatstep.getProxy()); webtest.addSteps(steps); WebtestTask.setThreadContext(new Context(webtest)); } public void testRepeatByXPath() { final List<Object> nodes = Arrays.asList(new Object[] { "foo", new Object(), new Integer(1) }); final SimpleXPathVariableResolver variableContext = getContext().getXPathHelper().getVariableContext(); final List<Object> actualNodes = new ArrayList<Object>(); final RepeatStep step = new RepeatStep() { protected List getNodesByXPath() { return nodes; } protected void executeContainedTasks(String _loopLabel) { final QName qname = new QName(getCounterName()); actualNodes.add(variableContext.resolveVariable(qname)); } }; configureStep(step); step.setXpath("/my/xpath/selecting/some/nodes"); step.execute(); assertEquals(nodes, actualNodes); } }