Every application has features. These features can be anything from the open file dialog in a GUI application to logging onto a web application. These features are referred to as "Functional Points" in Jameleon. Jameleon requires the tester to define the features of an application before or during the automation process. The best case scenerio would be to write your functional points before the application was actually written. As discussed in the overview document, there are three types of functional points:
These functional points are then mapped to the Jameleon Scripting Engine (Jelly). It is then, that through the scripting language that these functional points are grouped in the required order to execute, beginning where the other functional point left off.The following is a list of attributes supported by all function points, regardless of plug-in implementation.
A brief sentence explaining how the function tag is being used. For example, if using
a <logon/> action function tag to logon with invalid accounts, a possible functionId
might be Attempt logon with invalid accounts. This sentence is then used to generate
the test case documentation.
Sometimes a test case needs to be set up before it can run. For example, maybe a test case
tests the user delete function. To test the delete user function, a user must first be created.
However, if the test fails because a user couldn't be created, the test case that tests the
delete user function shouldn't fail normally because the add user function failed. It should
fail, but with an appropriate message. Setting a function tag as a precondition simply prepends
the error message with an precondition message,
Please see the precondition tag to group several function tags as
preconditions.
Sometimes a test case needs to be end in a state every time no matter what the outcome was.
When writing automated tests, it is best practice to make sure the test case leaves the
application being tested in the state it was in before the test was run. This can be accomplished
by usually just adding a function tag to this at the end of the test case. However, when a test
fails, no other function tags are executed. Now the function tag that is supposed to put the application
in the correct state doesn't get executed.
For example, maybe a test case tests the add user function. The test adds the user, just not as expected
and one of the validation points fails. Normally, a function tag to delete the user would be executed, but
now that a validation point failed, that clean up tag won't get executed.
This is what the postcondition setting is for. Any tag marked as a postcondition, will get executed no matter
what. If you have several tags that are postconditions, then all of them will get executed, whether one of the
postconditions fails or not. Please keep this in mind.
Please see the postcondition tag to group several function tags as
postconditions.
Sometimes, it is desired to test that something wrong happened. In this case expectFailure can be used
as a general way to make a function tag fail if it didn't fail due to a test (an assert method).
Sometimes, it is desired to test that an error happened. In this case expectError can be used
as a general way to make a function tag fail if an exception wasn't thrown.
This is mostly a GUI-specific feature for debugging scripts. If this is set to true and the script
is run with the Debug button, then the GUI will stop on this tag and wait.
Attribute Name Description Default Required functionId
N/A true functionDelay This is a numerical setting in milliseconds. Whatever this is set to,
the functional point will wait that period after execution. Defaults to "0" No precondition
false false postcondition
false false expectFailure
false false expectError
false false breakPoint
false false
Each plug-in must implement their own functional point. The current plug-ins are listed to the left. While the steps below describe the basic steps behind writing a function tag, be sure to click on the appropriate plug-in for specifics as to how to write tags for that particular plug-in.
Please refer to the section on the attributes supported by the base FunctionTag here.
Writing a functional point is quite easy. Simply follow the following guidelines.
Each plug-in has a FunctionTag which was written to be extended by all function tags for that specific plug-in. This function tag should exist in the net.sf.jameleon.plugins.plugin-name package and usually ends in FunctionTag. For example, in the JUnit plug-in there is a class named net.sf.jameleon.plugin.junit.JUnitFunctionTag.
To write a function tag, you must create a java class that extends the plug-in's function tag. So to write a function tag for the Jiffie plug-in, create a java class that extends net.sf.jameleon.plugin.jiffie.IEFunctionTag.
If using the jameleon-test-suite-x.x.x.zip package the Ant task that registers all tags expects that all tags end in Tag. If the tag isn't recognized by Jameleon even after building and registering, then this is likely the problem. Some bad tag name examples would be: AssertNull.java, Login.java, or CreateUser.java. None of those classes will be recognized by Jameleon. For them to be recongized, simply change their names to: AssertNullTag.java, LoginTag.java and CreateUserTag.java.
Implement a method called testBlock The public void testBlock() method is where the code that drives the tag must go. An example that checks whether the given value is contained with the provided text would look like:
public void testBlock(){ assertTextContains("some text that should contain some value", "some value"); }
It is best to come up with a good directory structure that represents the flow or functional areas of the application to be tested. Then place the Java implementation of that functional point in the corresponding directory and set the package accordingly. This will be very important once more than twenty or thirty functional points have been written. This helps make it easier to find functional points available for a certain application and/or functional area.
If the package statement in the java file doesn't match the directory structure, then your
tag will likely not get registered. Be sure to add the package statement at the top of your
tag. For example, if your java source files exist in the src/java directory and you
want a certain tag to exist in the admin/logon directory (src/java/admin/logon), then add
package admin.logon;
to the top of the java file.
Functional points will usually need to use variables that can be set via the test case script. To do this, simply ahere to the following guidelines:
Attribute Name | Description |
---|---|
required | Set this to true or false. If set to true and if the attribute isn't set in the script, then a failure will occur. Defaults to false. |
default | Sets the default value of the attribute to the value provided. If there is no value provided in the script then the value will be set to the default value |
contextName |
Binds the value to a context variable which is usually defined in a properties file. This is nice for
custom tags that use static data like form field names or titles. WARNING: This feature should not be used to communicate data between tags. This can make your scripts hard to read, difficult to debug and fragile. Thus it should be used sparingly. |
/** * The username of the logon * @jameleon.attribute required="true" */ protected String username; /** * The password of the logon * @jameleon.attribute default="foobar" */ protected String password; /** * The form name of the logon form * @jameleon.attribute default="foobar" contextName="appNameLogonFormName" */ protected String formName;
In order for Jameleon to recognize your function tag, you must javadoc it with the Jaemeleon-provided tags. These tags are used for both documentation and execution:
Tag Name | Description | Supported Attributes | Required |
---|---|---|---|
@jameleon.function | This tag is required for Jameleon to recognize your tag file. This tag tells Jameleon how to call the tag file. |
| |
@jameleon.step | For every step that would be required to execute this functional point manually, there should be one step. This is not a required javadoc. The test case docs will be generated based on all of the information in the javadocs. | No Attribute supported | |
@jameleon.application | The application that this functional point is used to test. This taglet can be used multiple times. The idea behind this is to help find which functional points can be used to test a given application. | No Attribute supported |
/** * Logs onto admin applications * @jameleon.function name="admin-logon" type="action" * @jameleon.step enter username * @jameleon.step enter password * @jameleon.step click the logon button * @jameleon.application userAdmin * @jameleon.application customerAdmin */ public class SomeTag extends JUnitFunctionTag{ }
The following is an example tag taken from an acceptance test tag in the Jiffie-plugin.
package foo.bar; import com.tapsterrock.jiffie.IHTMLFormElement; import com.tapsterrock.jiffie.IHTMLInputElement; import net.sf.jameleon.plugin.jiffie.IEFunctionTag; /** * Represents the customer information form on the blah application * @jameleon.function name="submit-customer-form" type="action" * @jameleon.step enter first name * @jameleon.step enter last name * @jameleon.step submit the form */ public class SubmitFormTag extends IEFunctionTag { /** * @jameleon.attribute required="true" default="formName" */ protected String formNameOrId; /** * @jameleon.attribute contextName="ieSubmitFormFirstName" */ protected String fName; /** * @jameleon.attribute contextName="ieSubmitFormLastName" */ protected String lName; public void testBlock(){ setWorkingForm(formNameOrId); setTextFieldValue("fName", fName); setTextFieldValue("lName", lName); submitWorkingForm(); } }
A use of this function point might look like:
<jmln:submit-customer-form functionId="Enter valid parameters" fName="Joe" ieSubmitFormLastName="Smith"/>
The above example sets the fName attribute directly and the ieSubmitFormLastName via the context. The lName attribute will then get the value Smith from the context variable.
Setting the values of the variables in the macro is as simple as defining attributes for that functional point.Jameleon provides a few custom Taglets to support the custom tags. An example of using these tags in an Ant task might look like:
<target name="javadocs" description="Creates JavaDocs for this project"> <delete dir="docs/javadocs"/> <mkdir dir="docs/javadocs"/> <javadoc packagenames="net.sf.jameleon.*" sourcepath="src/java" destdir="docs/javadocs" author="true" version="true" use="true" classpathref="classpath.with.ant"> <taglet name="net.sf.jameleon.taglet.JameleonFunctionTaglet" path="lib/jameleon.jar"/> <taglet name="net.sf.jameleon.taglet.JameleonStepTaglet" path="lib/jameleon.jar"/> <taglet name="net.sf.jameleon.taglet.JameleonAttributeTaglet" path="lib/jameleon.jar"/> </javadoc> </target>
This will generate javadocs for your custom functional points and include the tag name, steps and attributes in the javadocs.