-
Notifications
You must be signed in to change notification settings - Fork 44
JUnit
This component is an extension of JUnit framework that contains features useful during UI testing. It is not specific to any UI testing framework, although it is packaged as OSGI bundle.
It supports:
- preparing prerequisites required by the tests
- convenient configuration of such prerequisites (XML file)
- running the same test with different configuration files in one test run
Requirement represents one prerequisite of a test (e.g. created user or running server). It consists of two parts:
- requirement declaration (in a form of annotation)
- code for fulfilling the requirement (java class)
If the requirement cannot be fulfilled the test is not executed.That is the biggest difference from the @BeforeClass annotation from JUnit framework.
consists just from an annotation without any parameters and from the fulfilling class.
You have a test that requires admin user to be present in the database. You do not care if it is already there or not. If not, you want it to be created before the test methods are executed.
This is how you declare the requirement that admin user has to be present in the database:
@RunWith(RedDeerSuite.class)
@AdminUser
public class AdminUserTest {
@Test
public void test(){
}
}
This is how you create a class for fulfilling the declared requirement (the annotation needs to be an inner member of the class implementing Requirement interface)
public class AdminUserRequirement implements Requirement {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AdminUser {
}
public boolean canFulfill() {
// return true if you can connect to the database
return true;
}
public void fulfill() {
// create an admin user in the database if it does not exist yet
}
@Override
public void setDeclaration(AdminUser declaration) {
// no need to access the annotation
}
}
consists of an annotation with several parameters and from the fulfilling class that can access those parameters.
If you do not want a special requirement for each user you can create an annotation with user name parameter. The requirement fulfilling code will have access to that parameter and will create an appropriate user in the database if needed.
This is how you declare the requirement that user with name ''admin'' has to be present in the database:
@RunWith(RedDeerSuite.class)
@User(name="admin")
public class UserTest {
@Test
public void test(){
}
}
This is how you access the parameters of the declared annotation.
public class UserRequirement implements Requirement {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface User {
String name();
}
private User user;
public boolean canFulfill() {
// return true if you can connect to the database
return true;
}
public void fulfill() {
user.name();
// create a user with name admin in the database if it does not exist yet
}
@Override
public void setDeclaration(User user) {
this.user = user;
}
}
Red Deer JUnit component provides support for easy test run configuration by providing its own XML schema. To create a test run configuration you need to create the XML file and point Red Deer either to that file or to the folder containing several XML configuration files by specifying the following property on the command line:
-Dreddeer.config=/home/path/to/file/or/directory
You can make use of this configuration file to configure your own requirements in two ways:
- Use simple property based (key-value) configuration. You need to provide setter methods in you requirement class for each configuration property.
- Create your own XML schema that can be hooked into the XML configuratio file. You need to create a special configuration object that will be injected into your requirement.
Makes use of simple, property based, configuration in Red Deer configuration file. Mandatory XSD schema will be available on public site (you can wath the progress here: https://issues.jboss.org/browse/JBQA-6686). Until that you need to have it locally available in the configuration validation phase: attachment:RedDeerSchema.xsd
You probably do not want to hard-code some database information into your java code. You can put that configuration into Red Deer's configuration file.
<?xml version="1.0" encoding="UTF-8"?> <testrun xmlns="http://www.jboss.org/NS/Req" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.org/NS/Req RedDeerSchema.xsd"> <requirements> <requirement class="org.jboss.reddeer.wiki.user.db.simple.UserRequirement" name="userRequirement"> <property key="name" value="USERS_ADMINISTRATION" /> <property key="ip" value="127.0.0.1" /> </requirement> </requirements> </testrun>
This is how you declare the requirement that user with name ''admin'' has to be present in the database:
@RunWith(RedDeerSuite.class)
@User(name="admin")
public class UserTest {
@Test
public void test(){
}
}
Since it is possible to use requirements without any configuration, you need to let Red Deer know that you'd like to use property based config by implementing marking PropertyConfiguration interface.
public class UserRequirement implements Requirement, PropertyConfiguration {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface User {
String name();
}
private User user;
private String name;
private String ip;
public boolean canFulfill() {
// return true if you can connect to the database with the specified name and ip
return true;
}
public void fulfill() {
user.name();
// create an admin user in the database if it does not exist yet
}
@Override
public void setDeclaration(User user) {
this.user = user;
}
public void setName(String name) {
this.name = name;
}
public void setIp(String ip) {
this.ip = ip;
}
}
Makes use of Red Deer configuration file but provides its own XML schema. This is more complex than property based configuration but prevents you from typoes, allows you to refactor your code without a need for changes in configuration files and you can mark some properties as required so that XML schema validation will prevents you from forgetting some parameters. It is intended mainly if you provide your requirements for other teams or components.
You've got many configuration options or you are gonna to use the user requirements in several configuration files. You can create a simple XSD schema and read it using JAXB annotations and all withing Red Deer configuration file.
<?xml version="1.0" encoding="UTF-8"?>
<testrun
xmlns="http://www.jboss.org/NS/Req"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:user="http://www.jboss.org/NS/user-schema"
xsi:schemaLocation="http://www.jboss.org/NS/Req RedDeerSchema.xsd http://www.jboss.org/NS/user-schema user-schema.xsd">
<requirements>
<user:user-requirement name="user-requirement">
<user:db-name>USERS_ADMINISTRATION
<user:ip>127.0.0.1
<user:port>1111
</user:user-requirement>
</requirements>
</testrun>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://www.jboss.org/NS/user-schema"
xmlns:user="http://www.jboss.org/NS/user-schema"
xmlns:rd="http://www.jboss.org/NS/Req">
<!-- Import basic RedDeer requirements -->
<xs:import namespace="http://www.jboss.org/NS/Req" schemaLocation="RedDeerSchema.xsd" />
<!-- Specify user-requirement -->
<xs:element name="user-requirement" type="user:userRequirementType" substitutionGroup="rd:abstractRequirement">
<xs:annotation>
<xs:documentation>Specifies all data needed to create a user in the database
<!-- type for user-requirement -->
<xs:complexType name="userRequirementType">
<xs:complexContent>
<xs:extension base="rd:abstractRequirementType">
<xs:sequence>
<xs:element name="db-name" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="ip" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="port" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
This is how you declare the requirement that user with name ''admin'' has to be present in the database:
@RunWith(RedDeerSuite.class)
@User(name="admin")
public class UserTest {
@Test
public void test(){
}
}
To read the configuration from Red Deer's configuration file using your own schema you need to create a configuration object with JAXB annotaions.
@XmlRootElement(name="user-requirement", namespace="http://www.jboss.org/NS/user-schema")
public class UserConfiguration {
private String dbName;
private String ip;
private String port;
public String getIp() {
return ip;
}
@XmlElement(namespace="http://www.jboss.org/NS/user-schema")
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
@XmlElement(namespace="http://www.jboss.org/NS/user-schema")
public void setPort(String port) {
this.port = port;
}
public String getDbName() {
return dbName;
}
@XmlElement(name="db-name", namespace="http://www.jboss.org/NS/user-schema")
public void setDbName(String dbName) {
this.dbName = dbName;
}
Since it is possible to use requirements without any configuration or with property based configuration, you need to let Red Deer know that you'd like to use custom configuration by implementing CustomConfiguration. You'll also need to say the class of JAXB annotated object (called configuration).
public class UserRequirement implements Requirement, CustomConfiguration {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface User {
String name();
}
private User user;
private UserConfiguration userConfiguration;
public boolean canFulfill() {
// return true if you can connect to the database
return true;
}
public void fulfill() {
user.name();
userConfiguration.getDbName();
userConfiguration.getPort();
userConfiguration.getIp();
// create an admin user in the database if it does not exist yet
}
@Override
public void setDeclaration(User user) {
this.user = user;
}
@Override
public Class getConfigurationClass() {
return UserConfiguration.class;
}
@Override
public void setConfiguration(UserConfiguration config) {
this.userConfiguration = config;
}
}