Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.
ljelinkova edited this page Aug 1, 2012 · 8 revisions

JUnit Component

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

Requirements

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.

Simple Requirement

consists just from an annotation without any parameters and from the fulfilling class.

Example

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.

Requirement usage

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(){

        }
}

Requirement

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
        }
}

Requirement with parameters

consists of an annotation with several parameters and from the fulfilling class that can access those parameters.

Example

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.

Requirement usage

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(){

        }
}

Requirement

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;
        }
}

Requirements Configuration

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.

Requirement with property based configuration

Makes use of simple, property based, configuration in Red Deer configuration file. Mandatory XSD schema will is available on public site. Until than you need to have it locally available in the configuration validation phase (you can download it here: https://github.com/jboss-reddeer/reddeer/blob/master/org.jboss.reddeer.junit/resources/RedDeerRequirements.xsd).

Example

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.

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>

Requirement usage

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(){

        }
}

Requirement

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;
        }
}

Requirement with custom schema

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.

Example

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.

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>

XSD schema (user-schema.xsd)


<?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>

Requirement usage

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(){

        }
}

Requirement configuration

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;
        }

Requirement

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;
        }
}

Clone this wiki locally