// Copyright � 2002-2007 Canoo Engineering AG, Switzerland.
package com.canoo.webtest.steps;
import java.lang.reflect.InvocationTargetException;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Target;
import org.apache.xerces.xni.XNIException;
import org.xml.sax.SAXException;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.self.ErrorStepStub;
import com.canoo.webtest.self.FailStepStub;
import com.canoo.webtest.self.TestBlock;
import com.canoo.webtest.self.ThrowAssert;
/**
* Tests for {@link Step}.
* @author unknown
* @author Marc Guillemot
* @author Denis N. Antonioli
* @author Paul King
*/
public class StepTest extends BaseStepTestCase
{
private Step fFailSpec;
private Step fErrorSpec;
protected void setUp() throws Exception {
super.setUp();
fFailSpec = new FailStepStub();
configureTask(fFailSpec);
fErrorSpec = new ErrorStepStub();
configureTask(fErrorSpec);
}
protected Step createStep() {
return new StepStub();
}
public void testGetDescription() {
final Step step = getStep();
final String prefix = "PRE";
final String desc = "desc";
final String suffix = "POST";
assertEquals("", step.getDescription(prefix, suffix));
step.setDescription(desc);
assertEquals(prefix + desc + suffix, step.getDescription(prefix, suffix));
}
/**
* Test that expandDynamicProperties just uses what it needs from the properties map
* and not the rest allowing tricky use of this map to save (non String) objects
* from groovy (or any other script step) for reuse between 2 steps.
*/
@SuppressWarnings("unchecked")
public void testExpandDynamicProperties() {
final Step step = getStep();
step.getWebtestProperties().put("myProp", "something");
step.getWebtestProperties().put("myTrickyUseOfProps", new Object());
assertEquals("something", step.getProject().replaceProperties("#{myProp}"));
}
public void testLifecycle() {
assertStatus(getStep(), false, false, false, "before started notification");
getStep().notifyStarted();
assertStatus(getStep(), true, false, false, "after started notification");
getStep().notifyCompleted();
assertStatus(getStep(), true, true, false, "after completed notification");
getStep().notifySuccess();
assertStatus(getStep(), true, true, true, "after success notification");
}
public void testIsStartCompletedOnFailure() {
assertStatus(fFailSpec, false, false, false, "before execute");
ThrowAssert.assertThrows(StepFailedException.class, new TestBlock()
{
public void call() throws Exception {
fFailSpec.execute();
}
});
assertStatus(fFailSpec, true, true, false, "after execute with failure");
}
public void testIsStartCompletedOnError() {
assertStatus(fErrorSpec, false, false, false, "before execute");
ThrowAssert.assertThrows(StepExecutionException.class, new TestBlock() {
public void call() throws Exception {
fErrorSpec.execute();
}
});
assertStatus(fErrorSpec, true, true, false, "after execute with error");
}
public void testWebtestProperties() throws Exception {
final String propName = "count";
final String propValue = "2";
final RevealingStepStub openingStep = new RevealingStepStub();
configureStep(openingStep);
executeStep(openingStep);
openingStep.setWebtestProperty(propName, propValue);
assertEquals("empty string", "", openingStep.getProject().replaceProperties(""));
assertNull("null string", openingStep.getProject().replaceProperties(null));
assertEquals("prop only", propValue, openingStep.getProject().replaceProperties("#{count}"));
assertEquals("prop 1", "X" + propValue + "X",
openingStep.getProject().replaceProperties("X#{count}X"));
assertEquals("prop 2", propValue + propValue,
openingStep.getProject().replaceProperties("#{count}#{count}"));
assertEquals("no prop", "X", openingStep.getProject().replaceProperties("X"));
}
public void testExceptions() {
// dummy statements for coverage purposes: test default forms
// of exceptions which are catered for but not generally used
new StepFailedException("message").toString();
new StepExecutionException("message", (Throwable) null).toString();
}
public void testHandleUnexpectedException() {
checkUnexpectedException(fFailSpec, new StepFailedException("message", fFailSpec), StepFailedException.class);
checkExecutionException(new StepExecutionException("message", (Throwable) null));
final Logger log = Logger.getLogger(Step.class.getName());
final Level oldlevel = log.getLevel();
log.setLevel(Level.FATAL);
checkExecutionException(new NullPointerException("message"));
log.setLevel(oldlevel);
checkExecutionException(new SAXException("message"));
checkExecutionException(new XNIException("message", new RuntimeException("Nested")));
checkExecutionException(new XNIException("message", new XNIException("message", new RuntimeException("Double Nested"))));
checkExecutionException(new XNIException("message", new InvocationTargetException(new RuntimeException("Double Nested"))));
}
private void checkExecutionException(final Exception exception) {
checkUnexpectedException(fErrorSpec, exception, StepExecutionException.class);
}
private static void checkUnexpectedException(final Step step, final Exception exception, final Class throwable) {
ThrowAssert.assertThrows(throwable,
new TestBlock()
{
public void call() throws Exception {
step.handleException(exception);
}
});
}
public void testHandlesThrowableWithNoMessage() {
final String message = ThrowAssert.assertThrows(RuntimeException.class, new TestBlock()
{
public void call() throws Throwable {
getStep().handleException(new RuntimeException());
}
});
assertEquals("Unexpected exception caught: java.lang.RuntimeException", message);
}
public void testExecute() throws Exception {
assertExecute(new StepStub());
}
public void testDoExecute() throws Exception {
assertDoExecute(new StepStub());
}
private static void assertStatus(final Step step, final boolean started, final boolean completed,
final boolean successful, final String when) {
assertEquals("isStarted() should be " + started + " " + when, started, step.isStarted());
assertEquals("isCompleted() should be " + completed + " " + when, completed, step.isCompleted());
assertEquals("isSuccessful() should be " + successful + " " + when, successful, step.isSuccessful());
}
private void assertExecute(final Step step) {
configureStep(step);
step.execute();
assertTrue(((AbstractStepVerifierStub) step).isVerified());
assertTrue(((AbstractStepVerifierStub) step).isExecuted());
}
private void assertDoExecute(final Step step) throws Exception {
configureStep(step);
step.verifyParameters();
step.doExecute();
assertTrue(((AbstractStepVerifierStub) step).isVerified());
assertTrue(((AbstractStepVerifierStub) step).isExecuted());
}
public static class RevealingStepStub extends Step
{
public void doExecute() {
}
}
private abstract static class AbstractStepVerifierStub extends RevealingStepStub
{
private boolean fExecuted;
private boolean fVerified;
public boolean isExecuted() {
return fExecuted;
}
public boolean isVerified() {
return fVerified;
}
public void setExecuted(final boolean executed) {
fExecuted = executed;
}
public void setVerified(final boolean verified) {
fVerified = verified;
}
}
private static final class StepStub extends AbstractStepVerifierStub
{
public void doExecute() {
setExecuted(true);
}
protected void verifyParameters() {
setVerified(true);
}
}
public void testClone() throws Exception {
getStep().setLocation(new Location("myFile.xml", 15, 34));
getStep().setDescription("foo");
getStep().setOwningTarget(new Target());
getStep().setTaskType("myType");
getStep().setTaskName("myTask");
final Step clone = (Step) getStep().clone();
assertSameAndNotNull(getStep().getDescription(), clone.getDescription());
assertSameAndNotNull(getStep().getLocation(), clone.getLocation());
assertSameAndNotNull(getStep().getOwningTarget(), clone.getOwningTarget());
assertSameAndNotNull(getStep().getProject(), clone.getProject());
assertSameAndNotNull(getStep().getTaskType(), clone.getTaskType());
assertSameAndNotNull(getStep().getTaskType(), clone.getTaskType());
// don't need to duplicate because it can be the share between a step an its clone
// but in a first time, just test equals
assertEquals(getStep().getParameterDictionary(), clone.getParameterDictionary());
}
/**
* Test that expected object is not null and is the same as actual object.
*/
protected void assertSameAndNotNull(final Object expected, final Object actual) {
assertNotNull(expected);
assertSame(expected, actual);
}
}