0% found this document useful (0 votes)
26 views

Automated Testing of The Component-Based Web Application User Interfaces

This thesis explores testing of component-based web applications and develops a high-level API for testing user interfaces. It first reviews different types of software testing and trends in testing enterprise web applications. Tools for automated testing are evaluated based on criteria like maintainability. An object-oriented component model is then implemented using Java technologies to improve readability and maintainability of tests. The API is integrated with frameworks like WebDriver and deployed in a sample application to demonstrate functional testing.

Uploaded by

joeridley360
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views

Automated Testing of The Component-Based Web Application User Interfaces

This thesis explores testing of component-based web applications and develops a high-level API for testing user interfaces. It first reviews different types of software testing and trends in testing enterprise web applications. Tools for automated testing are evaluated based on criteria like maintainability. An object-oriented component model is then implemented using Java technologies to improve readability and maintainability of tests. The API is integrated with frameworks like WebDriver and deployed in a sample application to demonstrate functional testing.

Uploaded by

joeridley360
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 90

}w!"#$%&'()+,-.

/012345<yA|
Masaryk University
Faculty of Informatics

Automated Testing of the


Component-based Web
Application User Interfaces

Bachelor thesis

Juraj Húska

Brno, 2012
Declaration
Hereby I declare, that this paper is my original authorial work, which
I have worked out by my own. All sources, references and literature
used or excerpted during elaboration of this work are properly cited
and listed in complete reference to the due source.

Juraj Húska

Advisor: RNDr. Petr Ročkai

ii
Acknowledgement
I would like to thank RNDr. Petr Ročkai, the advisor of my thesis,
for his help, comments and time spent helping me with this work.
I am profoundly grateful to Bc. Lukáš Fryč for his guidance and
support throughout my work.
I would like to also thank Mgr. Marek Grác for his advices. My thanks
go to my parents, my girlfriend and my close friends as well.

iii
Abstract
This bachelor thesis explores and describes modern trends in testing
enterprise web applications. After the investigation, tools for automated
testing of these applications are selected and compared according to
maintainability, implementation of these tests and their usage in the
systems of continuous integration. Based on the analysis, a high level
application programming interface for using in testing the component
based web application user interfaces is implemented.

iv
Keywords
software testing, abstract component model, high-level API, Web UI
testing

v
Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Testing of enterprise web applications . . . . . . . . . . 3
2.1 Definition of testing . . . . . . . . . . . . . . . . . . . . . 3
2.2 Division of testing . . . . . . . . . . . . . . . . . . . . . . 3
2.2.1 According to way testing is performed . . . . . . 3
Manual testing . . . . . . . . . . . . . . . . . . . 3
Automated testing . . . . . . . . . . . . . . . . . 4
Benefits and drawbacks of both approaches . . . 4
2.2.2 According to depth . . . . . . . . . . . . . . . . . 6
White-box testing . . . . . . . . . . . . . . . . . 6
Black-box testing . . . . . . . . . . . . . . . . . . 6
Gray-box testing . . . . . . . . . . . . . . . . . . 6
2.2.3 According to scope . . . . . . . . . . . . . . . . . 7
Unit testing . . . . . . . . . . . . . . . . . . . . . 7
Integration testing . . . . . . . . . . . . . . . . . 12
System testing . . . . . . . . . . . . . . . . . . . 14
2.3 Continuous integration . . . . . . . . . . . . . . . . . . . 17
2.3.1 Key principles . . . . . . . . . . . . . . . . . . . . 17
2.3.2 Problems . . . . . . . . . . . . . . . . . . . . . . 18
2.4 Enterprise applications definition . . . . . . . . . . . . . 19
2.5 Enterprise testing approaches . . . . . . . . . . . . . . . 20
2.5.1 Other employed forms of testing . . . . . . . . . . 20
2.5.2 Example of enterprise testing process . . . . . . . 21
3 Evaluation of the tools . . . . . . . . . . . . . . . . . . . . 23
3.1 Criteria for choosing the tools examples . . . . . . . . . . 23
3.2 Selected tools . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.1 Arquillian Drone . . . . . . . . . . . . . . . . . . 24
3.2.2 Geb . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3 The results . . . . . . . . . . . . . . . . . . . . . . . . . 27
4 Component Model . . . . . . . . . . . . . . . . . . . . . . . 28
4.1 Motivation for creating the component model . . . . . . 28
4.1.1 Component based Web frameworks . . . . . . . . 30
4.1.2 Model requirements . . . . . . . . . . . . . . . . . 31
4.2 Object Oriented UI Testing Patterns . . . . . . . . . . . 32
4.2.1 Page Objects . . . . . . . . . . . . . . . . . . . . 32

vi
4.2.2 Component Objects . . . . . . . . . . . . . . . . . 36
4.3 Implementing the Component Model . . . . . . . . . . . 38
4.3.1 Employed Java technologies . . . . . . . . . . . . 39
Java Reflection . . . . . . . . . . . . . . . . . . . 39
Java Dynamic Proxies . . . . . . . . . . . . . . . 41
Java Generics . . . . . . . . . . . . . . . . . . . . 43
Service Provider Interface . . . . . . . . . . . . . 45
4.3.2 Integration with existing Frameworks . . . . . . . 45
WebDriver . . . . . . . . . . . . . . . . . . . . . 45
Arquillian Drone . . . . . . . . . . . . . . . . . . 48
4.4 Component Case Studies . . . . . . . . . . . . . . . . . . 52
4.4.1 Autocomplete component . . . . . . . . . . . . . 53
4.4.2 Table component . . . . . . . . . . . . . . . . . . 55
4.4.3 Calendar component . . . . . . . . . . . . . . . . 58
4.5 Real Deployment . . . . . . . . . . . . . . . . . . . . . . 60
4.5.1 Showcase application . . . . . . . . . . . . . . . . 60
4.5.2 Functional Tests . . . . . . . . . . . . . . . . . . 61
5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
A Example of UI test verbosity . . . . . . . . . . . . . . . . 70
B Factory class and its methods . . . . . . . . . . . . . . . . 71
C Test enricher . . . . . . . . . . . . . . . . . . . . . . . . . . 73
D Sequence Diagram of Autocomplete Component . . . . 74
E Sequence diagram of Table Component . . . . . . . . . . 75
F Sequence Diagram of Calendar Popup Component . . 76
G Omitted Arquillian test configuration. . . . . . . . . . . 77
H Manual for building showcase application . . . . . . . . 78
I Functional test without using of Component Model . . 79
J Functional test with using of Component Model . . . . 82
K Contents of Attached CD . . . . . . . . . . . . . . . . . . 84

vii
1 Introduction
Testing software is an important part of development of all applications.
For enterprise applications, however, it is inevitable. This is due the
fact that a development of enterprise applications is costly and time-
consuming, but carefully choosing improved testing methods leads to
cheaper development and maintenance [1].
At present time, an increasing number of applications, either en-
terprise or standard, is focusing on running in browsers, on desktops
and mobile devices. This is happening because a web application is
easier to distribute. The biggest benefit is that there is no need to
create a separate application for each platform. The rule "write once,
run everywhere" can be applied.
Testing the functionality of these applications is therefore highly
focused on User Interface (UI) testing. One way of reducing the cost
of developing and testing applications is automated testing. Present
development of scripts for automated UI testing, however, suffers from
many drawbacks. The way, in which tests are written, is too on low
level and therefore verbose, and also tightly coupled with a specific
implementation details of applications. Therefore, often a small change
in the application leads to many changes in tests, and thus provides
more opportunities to introduce errors into the test. Development and
maintenance of such tests is therefore expensive [2].
This thesis is aimed at exploring and describing modern trends in
testing enterprise web applications in the first phase, then after the
investigation, it is aimed at selecting tools for automated testing of
these applications, comparing them according to maintainability, imple-
mentation of these tests and their usage in the systems of continuous
integration. This analysis should provide high level application pro-
gramming interface (API) for use in testing the component based web
application user interfaces.
The work’s goal is to improve readability of tests and therefore also
the maintainability by employing the created API in testing of enterprise
applications.
An API is successfully adapted by users when it provides a clear
contract for each component; it should be easily employed; it shall evoke
confidence in users that the authors are able to maintain the API, and

1
1. Introduction

should build on already well-known projects. These are the objectives


that the API focuses on, as these are also the points that are considered
when deploying a new dependency in enterprise solutions.
The second chapter of thesis analyses the different types of testing
enterprise applications, and the third chapter compares selected tools for
automating UI testing. Integration and implementation of the created
API is described in Chapter 4. This chapter also describes the selection
of three major components, for which I created the API and their
implementation and their use in real-life example. Benefits of using the
created API are described in chapter 4 as well.

2
2 Testing of enterprise web applications

2.1 Definition of testing


Testing software is any activity aimed at evaluating an attribute or
capability of a program and determining that it meets its required
results [3].
Testing approach depends on the software development life cycle
model1 , and thus it needs to fit the model being used for the tested
project. However, a common objective of all approaches is to find the
problem as soon as possible, to reduce the cost of fixing it later [4].

2.2 Division of testing


The attributes of testing, like how big pieces of AUT (application under
test) we are testing, or what knowledge about AUT the tester2 has,
and the way testing is performed, divides testing activities into several
groups of types.

2.2.1 According to way testing is performed


Test can be executed manually by humans or automatically by comput-
ers.

Manual testing
It involves manual tasks, such as: setting up the test environment,
executing the tested functionality, collecting and reviewing the results
and recording found issues.
This process can be done by following a test plan or, alternatively,
by exploratory testing [5].

Following a test plan Test plan is a formal list of steps needed to


be done to test an application functionality. According to IEE 829-

1. The process of creating a software product from its initial conception to its
release [4].
2. The person who either performs tests, or who develops them.

3
2. Testing of enterprise web applications

2008 [6] it should contain among other things: a test plan identifier, an
introduction, test items, the features to be tested, the features not to
be tested, an approach, item pass/fail criteria, and other prerequisites.
Because it uses a predefined plan to test an application, it does not
depend tightly on tester’s skills. On the other hand, it can be more time
consuming to create and maintain test plans.

Exploratory testing It is not tied with any test plan, hence requires
less time for preparation, and can discover important problems quickly.
The problems are that it is harder to reproduce any discovered
problems in later application development phases, and exploratory
testing also tightly depends on tester skills.

Automated testing
Execution of tests without human intervention can be defined as au-
tomated testing. Automated tests execution includes, however, other
prerequisites [7]:

• Ability to run a subset of all tests.

• Automatic set-up and record environmental variables.

• Running the test cases.

• Capturing the results.

• Comparing actual and expected results and highlighting the


differences.

• Analysing the results and processing them in a comprehensive


and clear way.

Benefits and drawbacks of both approaches


Both manual and automated testing approaches have benefits as well as
drawbacks. An application context should help with deciding which one
is more suitable. The context includes following: how big the application
is, how big is the budget of the project, or when it should be released.

4
2. Testing of enterprise web applications

Manual testing benefits The set-up time is shorter in comparison


to automated testing. Moreover, it is possible to easily test manually
during all development phases, since there are no constraints on what
is suitable to test manually and what is not.

Manual testing drawbacks Repetitive and mundane tasks per-


formed during manual testing can lead to inaccurate or incorrect results.
The execution of tests is also slower than tests executed by a computer.

Automated testing benefits and drawbacks Automated testing


has benefits for bigger projects, since the initial cost for automation, and
test maintenance can be high. Some of the benefits and simultaneously
drawbacks are [1]:

• Automation helps to eliminate human errors - some of the mis-


takes which are made during manual testing can be reduced.
This concerns errors which were incurred by performing a long
list of mundane activities.
• Automated tests are faster than manual testing - this is consid-
ering only the actual execution of tests, it does not tell anything
about reviewing the results and then possibly fixing the broken
test. Because the execution is faster, the results are accumulated
faster too, hence the tester needs to review more results in a
shorter amount of time.
• Automation can lead to cost reductions.

To claim that automation can reduce costs, we need to firstly realize,


what is included to overall automation costs [1]:

• The cost of implementing a test harness3 .


• The cost of learning how to use the harness.
• The cost of developing automated tests.
• The cost of maintaining the tests as the product change.

3. Also called test driver, a tool used to execute and control tests.

5
2. Testing of enterprise web applications

• The cost of reviewing the test results.

This overall cost needs to be added to the cost of the remaining


manual testing costs, as some manual testing is still likely to be required,
especially when testing UI. This sum need to be compared to the sum
of manual testing only.

2.2.2 According to depth

Next chosen division is according to the attribute which reflects the


depth of tester insight into the tested application [4]:

White-box testing

It is also known as clear box testing, and denotes technique, when tester
knows the underlying implementation of an application, so he can decide
how to develop the tests according to this knowledge. It is used mainly
for checking small parts of an application, for example their database
transactions.

Black-box testing

It indicates the way of testing, where the tester does not know the details
of how the AUT works. An output of the tested action is important,
but not how the action was done. It is used mainly for testing of bigger,
already implemented parts of the AUT functionality.

Gray-box testing

It has both black-box and white-box testing characteristics. An example


of this is testing of functionality of web applications, because to perform
this type of testing, the knowledge of web page structure is required,
and simultaneously it is not important how the tested functionality was
performed.

6
2. Testing of enterprise web applications

2.2.3 According to scope


The last4 described attribute is a scope [8] of the testing. The scope
denotes the size of the tested parts, or more specifically, indicates the
number and the size of the parts, needed to achieve a tested functionality.
It also stands for the development cycle5 of the application it is currently
in, when the tests are written for it.
The motivation behind separating pieces which should be tested, is
that testing pieces in isolation allows identification of core fault easily.
Testing pieces of the application would lead to avoiding many sur-
prises when testing the entire product. In other words, when the fault
is found in an unit, then probably that unit is defective, when the fault
is occurring in two integrated units, it has to be related to how units
interact [4].

Unit testing
A unit is the smallest testable piece of software which can be compiled
and put under test harness [10].
Unit testing (sometimes module testing [4]) is typically performed
as white-box testing (see section 2.1), because the tester needs to know
the code which he is going to test [11].
Scope of unit testing is narrow, in other words, it should verify small
parts of the entire application. An example of unit testing can be testing
of an unit which is responsible for computing factorial of a natural
number.
Unit tests are usually written by developers of the application, or
framework. The tests should be developed and executed in prior to or
during the implementation of the modules [11]. It is not necessary to
wait with testing of units until all units are implemented because they
should not have dependencies on each other.

4. There are more attributes for dividing testing methods into groups, see [8] for
basic overview.
5. For example linear development methodology called Waterfall recognizes these
development phases: Initial Investigation, Requirements Definition, System Design,
Coding and Testing, Implementation, Operation and Support [9].

7
2. Testing of enterprise web applications

Formally it is standardized by, for example, IEEE Standard for


Software Unit Testing6 , which describes the exact process which should
be performed, its inputs and outputs.
When comparing unit testing with testing of bigger parts of AUT,
unit tests are often easier to develop, as they are more straightfor-
ward, and have less dependencies. Also running unit tests is less time-
consuming than running other types of tests.
The drawbacks come from the fact that with unit testing, we cannot
verify that an application is entirely flawless, even when we will be
testing all units. The problem is, that they are tested separately, and
after they will be integrated, some critical issues can arise.
Writing unit tests is laborious, cumbersome and often difficult task.
It is because the testing code is written at low level of abstraction,
therefore, it can be tedious to introduce a change in tests to match the
code under test changes [12]. Hence complete automation of unit testing
is not only feasible but also effective [13].
There are several tools which leverage unit testing and provide
integration with IDE (Integrated Development Environment)7 . In Java
environment, the most used frameworks are JUnit8 and TestNG9 , which
provide almost the same functionality nowadays, mainly the ability to
annotate a method with proper annotation to mark which method is a
test method, and then collecting results in some standard format, to
easily interpret them with IDE.

Mock versus real objects testing "Not all code is self contained"
[16], in other words, real applications have a lot of dependencies. Unit
tests are intended to test as much independent modules as possible.
This is, however, very hard to achieve in real world applications.10
The tester then has basically three options:
• test with real objects;

6. ANSI/IEEE Std 1008-1987, http://standards.ieee.org/findstds/


standard/1008-1987.html.
7. An application which provides environment for development, debugging and
more. An example is Eclipse [14] or NetBeans [15].
8. JUnit, http://www.junit.org/.
9. TestNG, http://testng.org/doc/index.html.
10. Applications not created with purpose of learning some technology, but to have
real addition.

8
2. Testing of enterprise web applications

• test with mock objects;


• test with stubs.

Real objects Testing with real objects would mean to use some
of the dependencies the tested unit has. But this means relying on the
fact that used dependencies are correct, that they are tested somewhere
else [16]. Suppose the listing 2.1.

1 import j a v a . u t i l . L i s t ;
2 import j a v a . u t i l . A r r a y L i s t ;
3
4 import o r g . my . f o o . Equipment ;
5
6 public c l a s s Garage {
7
8 // w i l l r e t u r n f a l s e i f t h e r e was c o r r u p t e d t o o l .
9 public boolean c h e c k T o o l s C o n d i t i o n ( L i s t <Equipment> t o o l s
) {
10
11 int numberOfTools = t o o l s . s i z e ( ) ;
12
13 f o r ( int i = 0 ; i < numberOfTools ; i ++) {
14 boolean good = ( t o o l s . g e t ( i ) ) . c h e c k C o n d i t i o n ( ) ;
15
16 i f ( ! good ) {
17 return f a l s e ;
18 }
19 }
20
21 return true ;
22 }
23 }

Listing 2.1: Example of using third party dependency to implement our


service.
On lines 9, 11 and 12, our artificial11 example depends on a third
party service, provided by imported dependencies of classes List and
ArrayList. When testing this service (Listing 2.2, line 17), we will be
also testing that these dependencies are working properly[16].

11. The intention is to just illustrate the use of Mock objects.

9
2. Testing of enterprise web applications

1 import j a v a . u t i l . L i s t ;
2 import j a v a . u t i l . A r r a y L i s t ;
3
4 import o r g . my . f o o . Equipment ;
5
6 public c l a s s TestGarage {
7
8 @Test
9 public void t e s t C h e c k T o o l s C o n d i t i o n ( ) {
10 Equipment axe = new Equipment ( " axe " ) ;
11 axe . s e t C o n d i t i o n ( ConditionEnum .BAD) ;
12
13 L i s t <Equipment> t o o l s = new A r r a y L i s t <Equipment >() ;
14 t o o l s . add ( axe ) ;
15
16 Garage g a r a g e = new Garage ( ) ;
17 boolean r e s u l t = g a r a g e . c h e c k T o o l s C o n d i t i o n ( t o o l s ) ;
18
19 a s s e r t F a l s e ( r e s u l t , " The method d i d not d i s c o v e r
corrupted tool ! " ) ;
20 }
21 }

Listing 2.2: Example of testing with real objects.


And that was not our intention. since we wanted to test only Garage
behaviours, isolated. Indeed, this is only an contrived example, but in
real world applications, reliance on the correctness of third party depen-
dencies can lead to bugs and unit test failures caused by malfunction
not of the Garage class itself. This kind of problems is often hard to
find and reproduce, and therefore should be avoided somehow.

Mock objects One of the solutions for this is to use mock objects
instead of real objects.
Mock objects encourage testers to write better structured tests with
reduced dependencies. It is a technique used in TDD (Test-Driven-
Development12 ) [18].
In other words, tester will mock the services provided by other than
tested class. He will define the exact behaviour the services should have,

12. Software development methodology which among the other things, encourage to
write tests at first, then implementation [17].

10
2. Testing of enterprise web applications

and by this, he does not suppose that the services works as expected
any more. It does not have to be used only in TDD, but in other testing
methodologies as well.
In Java environment, there are several mocking frameworks. Listing
2.3 demonstrates creation of a mock object in Mockito13 for dependencies
from Listing 2.2.

1 import j a v a . u t i l . L i s t ;
2 import j a v a . u t i l . A r r a y L i s t ;
3
4 import o r g . my . f o o . Equipment ;
5

6 public c l a s s TestGarage {
7
8 @Test
9 public void t e s t C h e c k T o o l s C o n d i t i o n ( ) {
10 Equipment axe = new Equipment ( " axe " ) ;
11 axe . s e t C o n d i t i o n ( ConditionEnum .BAD) ;
12
13 L i s t <Equipment> t o o l s = Mockito . mock ( L i s t . c l a s s ) ;
14 when ( t o o l s . g e t ( a n y I n t ( ) ) ) . thenReturn ( axe ) ;
15 when ( t o o l s . s i z e ( ) ) . thenReturn ( 1 ) ;
16
17 Garage g a r a g e = new Garage ( ) ;
18 boolean r e s u l t = g a r a g e . c h e c k T o o l s C o n d i t i o n ( t o o l s ) ;
19
20 a s s e r t F a l s e ( r e s u l t , " The method d i d not d i s c o v e r
corrupted tool ! " ) ;
21 }
22 }

Listing 2.3: Example of creating Mock object for third party


dependencies.

According to [18], after a revision of the initial definitions of Mock


objects, testers are encouraged to mock only dependencies they own.
In our example we should mock the Equipment class instead of List
interface.14

13. Mockito - Java Mock framework, more info at http://code.google.com/p/


mockito/.
14. The more information about why and the proper solution, can be found at [18].

11
2. Testing of enterprise web applications

Stubs Another solution for testing units without their external


dependencies is to replace these dependencies by stubs which are real
objects developed against defined interface to substitute functionality
of real implementation.
The difference between stubs and mock objects is that stubs need to
have predefined behaviour, while behaviour of mock objects is defined
at runtime.1516 .

Integration testing
Next level after testing units, is testing of integrated units, so-called
integration testing (sometimes product testing [11]).
These units are considered to be flawless, as their unit tests are
passing without problems, and we want to verify that aggregating of
these components cannot create a problem. An example of such problems
can be incorrect return value of a method call, or insufficient validation
criteria [10].
A special kind of integration testing is application programming
interface17 (API) testing. It is used, for example, to validate REST18
API, or an API of web components, which is done for this thesis.
Integration testing can be performed as both white-box and black-box
testing (see section 2.2.2). It should be performed by an independent
test team, and can begin as soon as enough of the tested units are
implemented, or when units need to integrate with components outside
of system, for instance with database.
During this phase, all customer environment variations should be
considered and tested [11]. Meaning that, for example, all supported
Operating Systems or browsers should be combined and tested.
Automation of integration testing is even more difficult than unit
testing automation. It is because of integration-level complexity, which
is firstly caused by complicated initial system set-up. To test integration

15. More information about differences between stubs and mock objects can be
found at http://martinfowler.com/articles/mocksArentStubs.html.
16. An example of a stub created for this thesis is AbstractComponentStub, which
can be found in the api module.
17. API, a specification intended to be used as an interface for communicating
among software components [19].
18. REST,http://www.ics.uci.edu/~taylor/documents/2002-REST-TOIT.pdf.

12
2. Testing of enterprise web applications

issues whole system need to be set to an initial state. Secondly it is


caused by problematic retrieving of tests results, suppose for example
retrieving results from testing of database transactions [20].
The challenge for web applications is that they often need to run in
an application container in order to work. The application container,
used mainly in Java EE19 , is an application which provides various
services for the AUT, such as handling concurrent access to the applica-
tion, management of application’s dependencies, or providing database
connections [21].
In such environment, there are application dependencies and services
which are often provided by a container. To provide this functionality
for tests, a tester has basically two options [22]:
• mock the application dependencies provided by a container as
described in subsection 2.2.3;
• or to deploy tests into container, and perform in-container testing.

Mock integration environment Using Mock objects brings an un-


certainty to our tests, because we cannot be sure that the application will
behave the same in the real environment, in this case, in the container.
To avoid this uncertainty, in-container testing can be employed.
On the other side, mocks allow us to run tests faster than in-container,
since they do not have to take unnecessary actions like parsing configu-
ration of the application.

In container testing This type of testing involves deploying our


tests to the container, execute them, and collect the results remotely.
It is also a typical example of gray-box testing (section 2.2.2), because
application container provides a logic which implementation is unknown.
Although this brings a significant advantage of having the depen-
dencies being provided by the container, it also brings another layer
to our testing infrastructure [22]. This layer represents a lot of new
code lines, or used dependencies which would manage shutting down
the application container, packaging and deploying the AUT, executing
tests and other.

19. Java Enterprise Edition, http://www.oracle.com/technetwork/java/


javaee/overview/index.html.

13
2. Testing of enterprise web applications

Hence, in-container testing pose problems with test readability and


maintenance, since the tester is not responsible for underlying imple-
mentation.

System testing
Several units aggregated into one make a component; several components
integrated into one make one big component, called system.
Testing of such big component is called system testing [10]. It is
aimed to reveal problems which can be exposed by only testing the
entire integrated system or a major part of it. An example can be an
error exposed by different communication network protocol, used for
communicating with other components or systems [11], or in case of
web applications, testing of user interfaces.
It is an example of black-box testing (section 2.2.2) and it is the
third phase according to target testing, during which the test team
should replicate application user environment. It should begin after all
components functionality was implemented.

Functional Testing It is similar to system testing, because it is a


kind of black-box testing (see the section 2.1), where the user point of
view is taken into account. Meaning that, the application is subjected
to various inputs, and its outputs are the subject to testing, because
they need to conform with specified behaviour [10].
The performance of functional testing on a web application, would
mean that a tester should verify functionality of all pages, all components
against various inputs. A simple example can be verification that, clicking
on the button would cause expected action.
Because testing of the web page functionality relates to testing of
the UI (User Interface), it has the same properties, both advantages
and disadvantages. One of the advantages is that it is quite clear what
to test and how to test, therefore it can be performed by less technically
trained people.

Automation UI testing problems Testing of User Interface


has some specifics. One of them is large basis of possible inputs, and
interactions which an user can perform with a web page.

14
2. Testing of enterprise web applications

Manual testing is, therefore, quite error-prone, as a tester can easily


forget to test some of the functionality from the specification, as he
is doing a repetitive task. It is also very time consuming, therefore
expensive. One of the solutions is exploratory testing (section 2.2.1).
These are the reasons that it is a good practice to have parts of the
functional testing of the web applications automatized. As section 2.2.1
described, one of the requirements to have tests automatized, is to have
defined a script which will instruct the particular testing driver, what
interactions with a tested web application need to be done. By this, the
execution of the tests can be repeated.
This script can be assembled in two ways, usually by a tool integrated
with a browser. Tool captures user interactions with the web application,
therefore, they can be repeated later. Second way is to define the script
programmatically, which means writing it with use of calling methods
from a testing tool API.
An example of the programmatic script is in Listing 2.4.

1 public c l a s s T e s t N a v i g a t i o n O v e r P a g e s {
2
3 private WebDriver d r i v e r ;
4

5 @Test
6 public void testPopup {
7 d r i v e r = new F i r e f o x D r i v e r ( ) ;
8
9 driver . get
10 ( " h t t p : / / l o c a l h o s t : 8 0 8 0 / myTestApp/ i n d e x . html " ) ;
11
12 d r i v e r . f i n d E l e m e n t (By . i d ( " button " ) ) . c l i c k ( ) ;
13
14 WebElement popup = d r i v e r . f i n d E l e m e n t
15 (By . xpath ( " //∗ span [ @id=’popup ’ ] " ) ) ;
16

17 a s s e r t T r u e ( popup . i s D i s p l a y e d ( ) , " The popup s h o u l d be


d i s p l a y e d , when c l i c k i n g on t h e button ! " ) ;
18 }
19 }

Listing 2.4: Example of programmatic script for testing simple web


application page.

15
2. Testing of enterprise web applications

When considering the Listing 2.4, it is noticeable that it exposes


some of the programmatic UI testing deficiencies20 , such as:

• Tests maintenance;
• Inability to test every aspect of the application
• Reliability of tests
• Non-effectiveness for some agile development methods
• Re-usability of the tests
• Slow speed of test execution

Tests maintenance - there is a hard-coded structure of tested web


page, on the lines 11 and 13. Should this structure change in the future,
the test will need to be changed as well. When considering 10,000 tests
for an application, this low level approach would mean increased costs
for tests maintenance. The best approach would be if the test class
could be abstracted from this structure.
Another problem is using of simple String objects, as a method
parameters, instead of type-safe21 way, which would include usage of
objects other than String, and therefore reflecting on their purpose.
This was just a very simple example of test, real UI tests tend to be
very verbose (see the appendix A)
These problems are more noticeable when maintaining several tests,
especially for an application which evolves.
Inability to test every aspect of the application - the script
is just testing that after clicking on the button, a pop-up is displayed.
Whether the pop-up was rendered correctly, that is, whether it is in
the correct place, with correct skin, and with a proper size would be
very difficult programmatically. Therefore, some of the web application
aspects still need to be tested manually.22

20. The deficiencies are not caused by tool selecting, they are very common for all
such tools.
21. It is a way of forcing a developer to use some particular type of the object, to
ensure discovery of type errors at compile time.
22. There are currently some tools which leverage some of the visual testing burdens,
but they can not still fully replace a human.

16
2. Testing of enterprise web applications

Reliability of tests - tools which use JavaScript browser engine to


instruct browser what interactions are need to be done for particular
test, are quite unreliable. Each browser has different JavaScript engine,
and testing on various browsers means writing browser-specific code for
some tests. This is, again, another load for test maintenance.
Non-effectiveness of some agile development methods - the
fact, that tests hold information about implementation structure, causes
that they need to be written after the implementation of tested func-
tionality. Hence, they are quite unusable with agile techniques like TDD
[23].
Re-usability of the tests - many parts of the tests are repeated
in other tests, because tested functionality requires common actions to
be done before the actual testing.
Tests tend to be slow to execute - the execution of simple test
can be measured in seconds. When running the whole test suite, it can
be increased to days to finish. This is quite a big problem in Continuous
Integration (CI) (see section 2.3) environment.

2.3 Continuous integration


Continuous integration has its roots in XP (Extreme Programming),
which is agile23 software development methodology, aimed to improve
software quality, while reducing time needed to respond to customer’s
constantly changing demands [24].
The software quality is improved by reducing the integration (see
the section 2.2.3) risk [25]. That is the risk of testing on the integration
level in the end of the product life cycle development, instead of testing
continuously to discover and fix possible errors as soon as possible.
Therefore, integration testing is feasible not only for integration testing,
but as well as for unit testing and system testing.

2.3.1 Key principles


To achieve better software quality, CI process has to duly observe
following key principles [25]:

23. Agile software development methods using practices of incremental a iterative


development.

17
2. Testing of enterprise web applications

• Application code should be maintained in the code repository.

• Build and tests of the application should be automated.

• Code changes should be delivered to the code base every day.

• Each delivering of the code should trigger project build and


testing process on dedicated machine.

• The building and testing should be as fast as possible.

• Test should be run in the production environment.

• Results should be clearly visible and authors of the code delivery


should be notified that their code delivery might cause failure.

• The latest version of application should be easily accessible, and


this process of releasing the application should be automatized.

2.3.2 Problems
The benefits which CI brings outweigh the disadvantages, but they need
to be considered as well. The most critical are:

• Initial investments into hardware, that is usually dedicated ma-


chine with CI tool running on it and its slaves on which the actual
CI build and testing is performed. The cost could be partially
limited by virtualization of some of the machines.24

• Security vulnerabilities need to be taken into account, because


an attack to CI system can mean disclosure of confidential infor-
mation or system shutdown, which can have a negative impact
on application development process.

• Tests need to be automatized, which can extensively increase the


overall development expenses.

24. Virtualization is a creation of virtual hardware platform, or operating system,


etc.

18
2. Testing of enterprise web applications

2.4 Enterprise applications definition


Enterprise applications are software products designed to facilitate co-
operation and coordination of work across the enterprise. It includes the
interconnection of core business processes like sales, accounting, finance,
human resources, and other. Very often, it also provides interfaces to
connect customers, suppliers and other business partners to that system
[26].
The more functionality they provide, the more complex they become.
There is also stress on proper development process to avoid unnecessary
costs and to provide product with sufficient quality.
As they often perform work with important data, which need to be
processed in real time, the focus is on other important aspects, and
challenges as well, like namely [27]:

• Performance;

• Data persistence;

• Accessing data concurrently;

• Numerous UI screens;

• Integration with other enterprise applications;

• Security.

Performance - is important for all kinds of applications but for enter-


prise software, it is often crucial, as their performance can significantly
influence the usability and the responsiveness to stimuli. These perfor-
mance deficiencies may have an impact on customers, therefore, can
cause significant monetary loss.
Data persistence - enterprise applications works with a lot of data
which need to persist not only between multiple runs of the application
but several years. The system has to be adaptable to the changes of the
data structure as new requirements for the new system functionality
emerge.
Accessing data concurrently - especially for Web enterprise systems,
there is a large number of users, who access the system concurrently.

19
2. Testing of enterprise web applications

Therefore, there has to be reliable mechanism to ensure, that this


concurrent access is not changing the data in a way that causes errors.
Numerous UI screens - a lot of data means a lot of distinct UI screens
that handle this data. They need to be presented in many various ways,
for all kinds of users, which can bring a lot of error-prone lines of code.
Integration with other enterprise applications - enterprise applica-
tions need to collaborate with other applications. The problem is, that
these applications are often built to run in different environments, writ-
ten in other programming languages. This, again, introduces a lot of
error-prone places in the application code.
Security - because enterprise applications control money and re-
sources, any security violation can cause, for instance, loss of confidential
or classified data, or other significant financial loss [28].

2.5 Enterprise testing approaches


In addition to forms of testing described so far, not only the enterprise
software employs other important forms of testing [29].

2.5.1 Other employed forms of testing


• The first described is Alpha testing. It is performed by the inter-
nal development team or quality assurance team in the controlled
environment, typically dedicated labs with an environment simu-
lating customers requirements. It is aimed to discover deployment
and workload issues, which need to be captured before the final
release.

• Acceptance testing is utilized for customized software and ap-


plications, designed for particular customer, rather than general
applications for broader base of users. The customer chooses a
user who will validate the application according to its specifica-
tion.

• Installation testing validates compatibility with hardware plat-


forms, that is, whether the application is portable to different
hardware and software platforms if this is requested by the cus-
tomer. The portability is the ability to run the application on

20
2. Testing of enterprise web applications

different hardware and software platforms without additional


changes required from the end user of application.

• Stress testing is used to simulate abnormal behaviour in a pro-


gram by considering situations that cause abnormal end of the
program, to create a benchmark of software stability.

• Smoke testing is aimed to test the code after the introduction of


a new code, to confirm that new changes do not compromise the
integrity of the product. Smoke tests should be fast to execute,
because they are often used to quickly validate the integrity of
the product, before deeper testing takes place.

• Usability testing measures the simplicity of using the application.


In case of applications with GUI (Graphical User Interface), these
interfaces are the subject of examination measuring for example
user accuracy or application response times.

2.5.2 Example of enterprise testing process


To meet the requirements from section 2.4, enterprise software needs to
be tested in a proper way.
To test the application properly, there is a need to test every feature
of the product on every possible configuration [11].
This can be, however, very exhausting process. Therefore, there is a
demand for efficient testing. We need to find an approach which enables
finding most of the problems, for as reasonable cost as possible [11].
Hence, a big emphasis is put on the automated testing. In other
words, what can be automated is automated, the rest is done manually.
CI is another employed technique, into which a lot of funds is invested.
It is usually the most important part of the testing structure, thus is
critical for enterprise products.
Figure 2.1 shows an example of enterprise testing process time-line
[11] [29]. First Milestone is a term for first development milestone, when
the application is in the state, when the system testing can begin. Code
freeze is the state when no additional code changes are allowed.

21
2. Testing of enterprise web applications

Figure 2.1: An example of enterprise testing process time-line.

22
3 Evaluation of the tools

3.1 Criteria for choosing the tools examples


The aim was to choose several tools for automated testing of the en-
terprise web applications and consequently compare them according to
maintainability, implementation of these tests and their usage in the
systems of continuous integration.
From the variety of web UI automation testing tools [30], I choose
and concentrated mainly on tools which are suitable for enterprise usage.
That means, they have to provide cross-browser testing ability. In other
words, they have to support all major browsers, which are currently
Firefox, Internet Explorer, Safari, and Google Chrome1 , on the major
Operating Systems platforms (Linux, Windows, Mac).
The selected tools have to be able to provide programmatic way
of creating test scenarios as we believe, this would be the way to
enable further maintainability improvements and CI integration. Test
automation is very similar to software development, therefore, the same
logic can be applied [2].
Next requirement was that the selected tool has to be open sourced2 ,
which allows use of this tool as a base for the created component model.
The tool has to be enabled for testing rich web applications. In other
words, it has to support testing of Ajax-based web sites.
I focused on projects with well based community behind them, as
enterprise solutions usually cannot afford to invest money into unstable
or small-scale projects. The best way was to choose project with a
financial supporter behind it, as for example a big software company
which either employs the framework developers or provides other support
for it.

3.2 Selected tools


According to criteria for selecting from section 3.1, I chose following
frameworks:

1. See reference [31].


2. Open Source, http://www.opensource.org/docs/OSD.

23
3. Evaluation of the tools

• Arquillian Drone [32]

• Geb [33]

3.2.1 Arquillian Drone


Arquillian is a testing platform that enables developers to create au-
tomated integration, functional and acceptance tests. Its main focus
is on separating the test and the runtime, so a tester can concentrate
on test logic rather than on managing the runtime from the test. This
brings lot of benefits for an in-container testing 2.2.3, while Arquillian
is eliminating the burden connected with it. Among other things, it
manages following:

• The life cycle of the application container.

• Packages test cases and other dependencies into an archive.

• Deploys this archive to the containers.

• Enriches the test case by Dependency Injection (DI).3

• Executes the test inside or against the container.

• Collects the results remotely and returns them for reporting.

I chose Arquillian extension called Drone. It inherits all aspects of


Arquillian, and furthermore adds support for managing life cycle of
browser.
The list of supported browsers begins as it is required with the major
used browsers. Since Arquillian was created to be highly extendable it
also enables to add support of any desired browser.
Drone is not a driver itself, it integrates with existing drivers, such
as Graphene [34] and automation tool Selenium 24 which is a union of
Selenium 1 and project WebDriver5 .
Graphene is a wrapper for Selenium, that was created to provide
type-safe way of using the Selenium API, and other tools for testing an

3. DI, http://martinfowler.com/articles/injection.html.
4. Selenium 2, http://seleniumhq.org/.
5. Selenium, http://seleniumhq.org/docs/03_webdriver.html.

24
3. Evaluation of the tools

Ajax enabled web pages. An Arquillian project is configured via Apache


Maven6 build system.
An example of a test written in Arquillian Graphene for an artificial
application, can be found in Listing 3.1.
It is shortened, as for example Java imports statements are left to
keep it readable. Also the method for deployment of AUT is left. The
example of this deployment method can be found in appendix G, where
AUT is assembled with the use of ShrinkWrap7 project.
In following listing, line 1 indicates that it is an Arquillian test, line 3
and 4 is DI for context root, that is, the root part of the URL which will
be accessed in order to load the application in the particular browser.
Line 6 and 7 injects the driver which is in this example Arquillian
Graphene, via which the browser is instructed.
On the lines 9-25 a test is declared that simply fills some characters
in the input, triggers an Ajax action and asserts that the generated
output is the same as the inserted characters.

1 public c l a s s TestMyApp extends A r q u i l l i a n {


2
3 @ArquillianResource
4 protected URL c o n t e x t R o o t ;
5

6 @Drone
7 protected AjaxSelenium s e l e n i u m ;
8
9 @Test
10 public void t e s t A j a x I n p u t ( ) {
11

12 s e l e n i u m . open ( URLUtils . b u i l d U r l ( contextRoot ,


" /myApp/ i n t e x . html " ) ) ;
13
14 S t r i n g t e s t S t r i n g = " Test S t r i n g " ;
15
16 JQueryLocator i n p u t = j q ( " . myInput " ) ;
17
18 s e l e n i u m . typeKeys ( input , t e s t S t r i n g ) ;
19 guardXhr ( s e l e n i u m ) . f i r e E v e n t ( input , Event .KEYUP) ;
20
21 JQueryLocator ajaxOutput = j q ( " . myOutput " ) ;

6. Apache Maven, http://maven.apache.org/.


7. ShrinkWrap, http://www.jboss.org/shrinkwrap.

25
3. Evaluation of the tools

22

23 S t r i n g actualOutput =
s e l e n i u m . getText ( ajaxOutput ) . t r i m ( ) ;
24 a s s e r t E q u a l s ( actualOutput , t e s t S t r i n g , " The output
g e n e r a t e d by Ajax i s not c o r r e c t ! " ) ;
25 }
26 }

Listing 3.1: Example of test written in Arquillian Graphene.

3.2.2 Geb
Geb is the second chosen tool. It also uses WebDriver internally together
with JQuery8 content selection. It is similar to Arquillian Drone in terms
of cross-browser testing and ability to test asynchronous pages.
The differences from Arquillian Drone is that the test scenarios
are written in Groovy. And it also lacks the Arquillian support for
management of test life cycle. Apache Maven can be used for building.
Support for Gradle9 and Grails.10 is added.
An example of test written in Geb is shown in Listing 3.2. The test
scenario is the same as in listing 3.1.
On line 2, it is accessing the URL on which the tested application is
deployed, line 4 ensures that the tested page was completely loaded.
On line 6, it is using JQuery like syntax for locating of element with
class myInput, and consequently the found element is filled with value
Test String.
Line 8 asserts that the element with class myOutput was updated
with expected value.

8. JQuery, http://jquery.com/.
9. Gradle, http://www.gradle.org/.
10. Grails, http://grails.org/.

26
3. Evaluation of the tools

1 Browser . d r i v e {
2 go " h t t p : / / l o c a l h o s t : 8 0 8 0 /myApp/ i n t e x . html "
3
4 a s s e r t t i t l e == "MyApp"
5
6 $ ( " i n p u t " , c l a s s : " myInput " ) . v a l u e ( " Test S t r i n g " )
7
8 waitFor { $ ( " d i v " , c l a s s : " myOutput " ) . t e x t ( ) == " Test
String " }
9 }

Listing 3.2: Example of test written in Geb

3.3 The results


After the evaluation I would like to single out Arquillian Drone.
There are several reasons for it. The first would be the Arquillian
container management support which gives us a great tool to use in
CI. Geb is also supported in CI. However, lot of functionality has to be
implemented by the user to obtain the same result as with Arquillian.
Arquillian is also easily extendable which gives us an opportunity to
integrate our project with Arquillian Graphene later on. It also supports
so called extensions which will help us to enhance usability of our created
API.
When considering the listings 3.1 and 3.2, at first glance it is notice-
able that Geb example is less verbose, however, it does not provide the
users with the functionality that Arquillian Graphene does, for instance
the way how Graphene ensures that an Ajax event was fired (line 19).
Another advantage of Arquillian Graphene tests is its type-safety.
Possible flaws of code lines in JQuery syntax can be only found at
runtime. This makes Arquillian Graphene tests more robust and there-
fore, more suitable for enterprise environment. It also enables the users
to encapsulate the components in more readable way, hence better
maintainable way, which will be useful later in API creation.

27
4 Component Model
A component is a basic unit of the component-based Web frameworks
(section 4.1.1). That is, for instance a calendar component. A graphical
representation of the calendar component can be found in the figure 4.1.
The term component model is used for the purpose of this thesis as
a term for referencing an abstract API an its implementation, that was
created for this thesis.

Figure 4.1: Calendar component - RichFaces implementation.

4.1 Motivation for creating the component model


Users of RichFaces framework (section 4.1.1) demand a way to easily test
their enterprise applications. A component model was created to help
them. The model encapsulates behaviour of all RichFaces components.
These components will be then used in functional tests, to enhance
tests maintainability, by encapsulating the structure of HTML code
for particular component at one place. This way we could avoid code
repetition and incidental details [2], which are the main inhibitors to
introduce a change in the software.
The idea was, instead of writing tests like demonstrated in Listing
4.2, write tests similar to the test demonstrated in Listing 4.1. Both
tests on listings verify simple test scenario, where setting the current

28
4. Component Model

date to the calendar will be correctly reflected in the input for that
calendar.
Note the differences: whereas in the first example the structure of
the web page is hard-coded in the test, the second example uses services
of calendar component which encapsulates that structure to achieve the
same functionality. This way it is more visible what the purpose of test
is. Furthermore, the more readable the code is, the better maintainable
it is.

1 public c l a s s T e s t C a l e n d a r {
2
3 @FindBy ( xpath = " // d i v [ @id=’ ro ot E le me nt ’ ] " )
4 R i c h F a c e s C a l e n d a r c a l e n d a r = new
RichFacesCalendar ( " locatorDeterminingCalendar " ) ;
5
6 @Test
7 public void t e s t A j a x I n p u t ( ) {
8 Date e x pe c t ed D a te = new Date ( ) ;
9
10 c a l e n d a r . show ( ) ;
11 c a l e n d a r . setToday ( ) ;
12
13 Date a c t u a l S e t D a t e = c a l e n d a r . g e t S e t D a t e ( ) ;
14

15 checkThatDatesAreSame ( expectedDate , a c t u a l S e t D a t e ) ;
16 }
17 }

Listing 4.1: Test for RichFaces calendar Arquillian, using component


model.

1 public c l a s s T e s t C a l e n d a r {
2
3 protected JQueryLocator imgWhichInvokesTheCalendar =
j q ( " img . r f −c a l −btn " ) ;
4 protected JQueryLocator applyButton =
j q ( " d i v [ o n c l i c k ∗= c l o s e ] : c o n t a i n s ( ’ Apply ’ ) " ) ;
5 protected JQueryLocator todayButton =
j q ( " d i v [ o n c l i c k ∗=today ] : v i s i b l e " ) ;
6 protected JQueryLocator c a l e n d a r I n p u t =
j q ( " . r f −c a l −i n p " ) ;
7
8 @Test

29
4. Component Model

9 public void t e s t A j a x I n p u t ( ) {
10 s e l e n i u m . c l i c k ( imgWhichInvokesTheCalendar ) ;
11
12 waitGui . f a i l W i t h (new RuntimeException ( " Calendar was
not opened ! " ) )
13 . timeout (1000)
14 . u n t i l ( e l e m e n t V i s i b l e . l o c a t o r ( todayButton ) ) ;
15
16 s e l e n i u m . c l i c k ( todayButton ) ;
17 s e l e n i u m . c l i c k ( applyButton ) ;
18
19 waitGui . f a i l W i t h (new RuntimeException ( " Calendar was
not c l o s e d ! " ) )
20 . timeout (1000)
21 . u n t i l ( e l e m e n t N o t V i s i b l e . l o c a t o r ( todayButton ) ) ;
22
23 Date e x pe c t ed D a te = new Date ( ) ;
24 Date a c t u a l S e t D a t e =
parseDateFromInput ( c a l e n d a r I n p u t ) ;
25
26 checkThatDatesAreSame ( expectedDate , a c t u a l S e t D a t e ) ;
27 }
28 }

Listing 4.2: Test for RichFaces calendar in Arquillian Graphene.

Moreover this API does not have to reflect only on specific implemen-
tation of UI components, it can be transformed to provide unified API
for various UI component libraries. These libraries can be collectively
called component based frameworks.

4.1.1 Component based Web frameworks


In the Java environment, component based frameworks, also known as a
pull-based architectures, duly follow the MVC (Model-View-Controller)1
pattern.
As opposed to the action-based architectures2 these frameworks start

1. MVC is an architectural pattern which separates an application into three main


components: the model(business logic), the view (user interface), and the controller
(user input) [35].
2. Action-based (push-based sometimes), since they use actions that do required
processing and then push the data to the view layer, examples: Spring MVC, Struts
[36].

30
4. Component Model

with the view layer by providing set of core components which pull
results from multiple controllers3 as needed. [36] This means that, the
components are managing the requests on their own, they do not need
the developer to implement various interfaces to achieve the desired
functionality. Examples of such frameworks are: JSF (Java Server Faces),
Tapestry, Wicket, GWT (Google Web Toolkit), Vaadin as well as Stripes.
Component oriented4 frameworks can be identified also in other
environments apart from Java. For instance ASP.NET Web Forms
is a framework which also provides set of components for which the
component model can be created.
The last example of the environment where Web components play a
significant role is JavaScript environment, an example is the jQuery UI
framework.
All above mentioned frameworks have one important characteristic
in common: each component has predefined the HTML mark-up code
which is rendered on the client side (browser) and also the JavaScript
sources which are either included or imported to the page sources
rendered by the browser.
This particular specific of these frameworks enables us to create an
implementation of the predefined abstract component model in a way
that allows all users of that framework to employ it.

4.1.2 Model requirements


From the motivation of creating such a model as in4.1 arise model
requirements, which can be defined as follows:

• The API should be written in the way, that would provide


methods for basic use cases of the particular component. In other
words, the majority of the components from different frameworks
should be able to implement that particular API.

• It should provide cross browser compatibility for testing.

• It should support rapid development and enhance a type safety.

3. Controller is that part of the MVC which handles user input and controls the
data flow from business logic to the View layer.
4. Do not meet all the specifics of the component based frameworks.

31
4. Component Model

• It should be integrated with selected framework (Arquillian


Drone) from tools evaluation, chapter 3.

Those are the general requirements. However, there were other


demands on the abstract model. Particularly, we need to define a mech-
anism to determine what component we are communicating with, since
there can be several components of the same type on one tested web
page.
The created API and its implementation should encourage testers
to use object oriented testing patterns (see the following section).

4.2 Object Oriented UI Testing Patterns


Regarding to model requirements we are identifying various UI testing
patterns. one of them is Page Objects patter. As all patterns, this one is
also a result of experience, and this comes particularly from automation
of UI tests.

4.2.1 Page Objects


Its main objective is to model Web page areas into objects to reduce
the amount of the duplicated code and also to enhance the tests main-
tainability [37].
The key principles used to achieve this and best practices for working
with Page Objects are [37]:
• the HTML structure of the page is defined only in one place - so
that the change in the HTML code will affect tests as little as
possible
• Page Objects expose services to developers, in other words provide
methods to interact with page
• these methods should again return other Page Objects - this
encourages test developers to interact rather with the services
than with the implementation. As a result they are able to control
which tests will fail. Easily said, it means better maintainability
• Page Objects do not have to represent whole web site, they can
be just part of it

32
4. Component Model

An example of such Page Object can be the online translate service


(Google Translate5 ) provided by Google Inc.
The primary service it provides is of course translating from one
language to another. But to do so, user often need to choose both from
and to which language to translate particular word.
Programmatically speaking, implementing the Page Object for such
a Web page using the WebDriver can be written as the code snippet
4.3. The connection between this code and the Google Translate page is
represented in a more comprehensive way in figure 4.2.

Figure 4.2: Screenshot of Google Translate page (20th April 2012) with
references to the code lines from 4.3.

1 public c l a s s G o o g l e T r a n s l a t e {
2
3 @FindBy ( xpath = " // i n p u t [ @type=’ submit ’ ] " )
4 private WebElement t r a n s l a t e B u t t o n ;
5
6 @FindBy ( xpath=" // t e x t a r e a [ @id=’ s o u r c e ’ ] " )
7 private WebElement inputArea ;
8

5. Google Translate, http://translate.google.com.

33
4. Component Model

9 @FindBy ( xpath=" // span [ @id=’ r e s u l t _ b o x ’ ] " )


10 private WebElement r e s u l t A r e a ;
11
12 public S t r i n g t r a n s l a t e ( S t r i n g word ) {
13 inputArea . sendKeys ( word ) ;
14 translateButton . c l i c k () ;
15

16 (new WebDriverWait ( webDriver , 4 ) ) . u n t i l (new


ExpectedCondition <Boolean >() {
17
18 public Boolean apply ( WebDriver d ) {
19 return ( r e s u l t A r e a . getText ( ) . t r i m ( ) . l e n g t h ( ) > 0 ) ;
20 }
21 }) ;
22
23 return r e s u l t A r e a . getText ( ) . t r i m ( ) ;
24 }
25
26 public void s e l e c t L a n g u a g e T o T r a n s l a t e T o ( Language
language ) {
27 // implemented i n t h e s i m i l a r way
28 }
29
30 public void s e l e c t L a n g u a g e T o T r a n s l a t e F r o m ( Language
language ) {
31 // implemented i n t h e s i m i l a r way
32 }
33 }

Listing 4.3: Google Translate - example of Page Object written in Java


programming language.
As it is in accordance with the best practices this Page Object can
be used in the functional test of the translating service as demonstrated
by the code snippet.
What was meant by best practices is that only the GoogleTranslate
object distinguishes the HTML structure of the real web page. Better
said, it holds this information in WebElement objects - e.g. it knows
that the translated result area has id set to result_box value. This
Page Object can be used in the functional test of the translate service
as demonstrates the code snippet.4.46
Let’s suppose that you want to use interaction with the Google

6. It is only truncated example of Arquillian test.

34
4. Component Model

Translate in other test scenarios, or rather in other test methods, classes


or even projects. Then imagine that the Translate button will be removed,
and the translation will be triggered automatically, during filling in the
input the particular word by releasing the key.
The above mentioned does not have to be just artificial change
scenario. This can be easily done later for rendering that page on mobile
devices, as the automated translation has already been implemented.
Furthermore, it is needed to render as few items on mobile devices as
possible.7
Then the only place which will need to be changed will be the Page
Object, all dependent test classes will remain untouched. Hereby we
reach the goal, enhancing tests maintainability.

1 public c l a s s T e s t G o o g l e T r a n s l a t e extends A r q u i l l i a n {
2
3 @Page
4 private G o o g l e T r a n s l a t e g o o g l e T r a n s l a t e ;
5
6 @Drone
7 WebDriver webDriver ;
8
9 @Test
10 public void t e s t T r a n s l a t e W o r d ( ) {
11 g o o g l e T r a n s l a t e . s e l e c t L a n g u a g e T o T r a n s l a t e F r o m (new
Language ( " sk " ) ) ;
12 g o o g l e T r a n s l a t e . s e l e c t L a n g u a g e T o T r a n s l a t e T o (new
Language ( " en " ) ) ;
13
14 S t r i n g wordToTranslate = " ryba " ;
15 String expectedTranslation = " f i s h " ;
16
17 String actualTranslation =
g o o g l e T r a n s l a t e . t r a n s l a t e ( wordToTranslate ,
webDriver ) ;
18

7. The reason is obvious, as mobile devices have smaller screens, mobile application
developers need to save space as well as size of requested data.

35
4. Component Model

19 assertEquals ( actualTranslation , expectedTranslation ,


" The word was t r a n s l a t e d i n c o r r e c t l y ! " ) ;
20 }
21
22 }

Listing 4.4: Example of the Arquillian functional test of the Google


Translate page, written in the Java language.

In the abstract model created for this thesis, Page Objects are
supported as demonstrated on lines 3 and 4 in figure 4.4. Note the
differences between default WebDriver project and created model.
Prior to the usage of the particular Page Object, this object needs to
be initialised properly. It means that all WebElements of that Page Ob-
ject (lines 4, 7, 10 in code snippet 4.3) need to be initialised with a proper
object so that they would not encounter NullPointerException.8
As opposed to WebDriver project, this initialisation is done with use
of a factory method. We have implemented Page Java annotation(line
3 in code snippet 4.4) which will be recognized in the runtime by
Drone extension and initialized with particular Page Object. Further
information about integration with this extension is described in section
4.3.2.

4.2.2 Component Objects


Another pattern, or better said good OO (Object Oriented) approach
to design reusable code is Component Object. It is very similar to the
Page Objects. It also indentifies parts of the Web page and its services,
however in a finer grained way. The objective of this is to provide
components which are highly reusable. This pattern will be used mainly
for creation of the API, its consequences are particular components.
It is based on Component-Based Architectural Style. This style
provides a higher level of abstraction by decomposing of the design
into logical or individual components that expose well-defined interfaces
containing methods, events, and properties.
Components designed in this style should follow following principles
[38]:

8. Java Exception thrown e.g. when invoking method on field with null value.

36
4. Component Model

• Reusable - they should be designed in a way to be easily reused


in other parts of the same or different application;

• Replaceable - components should be easily replaced by other


components;

• Not context specific - the state should not be included into


components, it should be passed to them;

• Extensible - to provide a new behaviour, a component should be


easily extended;

• Encapsulated - basic OO rule that methods should not expose


the internal implementation, variables or state;

• Independent - in order to use components in other environments,


there should be minimal number of the component’s dependen-
cies.

Abstract component model implemented for this thesis are trying


to meet this requirements. Components are reusable across all projects,
they are defined in the Java, but the implementation can describe any
component-based Web framework. 4.1.1 They can be easily added to
your project as Apache Maven.
One implementation of the component can be replaced by another.
This is achieved by defining at first common interface for that component.
Then, with regards to the another OO design principle, program to
an interface, not an implementation [39], the component dependency
can be replaced by the other component, as the second component also
implements the common interface.
The interfaces for components do not contain state, however, the
implementation does. This is the specific of the component-based frame-
works. The framework that the HTML code generated for the particular
component is the same for all applications. More information about this
specific can be found at the section 4.1.1. Another state which needs
to be accessible for components, is which browser they are rendered
on. However, this information is injected into them in runtime by Ar-
quillian DI (Dependency Injection) mechanism, so it is not wired with
components.

37
4. Component Model

The implemented components are also extensible, because the imple-


mentation classes are non final and define public constructors, or to be
more precise they do not define private constructors. The new behaviour
can be then added by the standard extension Java mechanism. It is
then on the developer, whether his components will be extendable or
not, but the standard ones, from the abstract model are.
Components are encapsulated by encapsulating all the methods,
in other words, the Javadoc9 and the names of the methods are not
exposing how their service is done, which means that the particular
implementation is hidden.
Let’s take the Google Translate Web page into consideration one
more time. This time the whole page will be divided into smaller parts.

Figure 4.3: Google Translate Web page screenshot (20th April 2012)
with components identified.

Several components can be identified in the Web page from figure4.2.


These components can be used in other pages. Among the simple
components we can see following: button, select and text area, continuing
with more complex like tab panel or virtual keyboard. The figure 4.3
shows a graphical representation of those.

9. Javadoc - way of creating documentation for Java methods, classes and other
structures.

38
4. Component Model

4.3 Implementing the Component Model


All previous sections described our component model in general way.
Following sections will describe the implementation in detail.

4.3.1 Employed Java technologies


Above all, we need to define which specifics of Java programming
language we used for implementating component model.

Java Reflection
Reflection is a feature of Java language, used by programs to examine, or
modify the runtime behaviour of applications. It is an advanced feature
which needs to be employed with following concerns kept in developer’s
mind [40]:

• Performance overhead, because Java virtual machine10 (JVM)


optimizations can not be done for dynamically resolved reflection
types, parts of the code which use reflection have slower perfor-
mance, and therefore in performance demanding applications,
using of reflection should be considered carefully;

• Security restrictions, when the application is running under se-


curity manager11 , some of the required reflection permissions do
not have to be permitted;

• Exposure of internals, because with use of reflection operations,


it is for example possible to access private12 fields and methods,
it can have unexpected side-effects, and can destroy portability
of the application. Reflection behaviour can be changed with
upgrades of Java platform, which can cause that application
cease to function.

10. The environment where all Java applications run.


11. A mechanism in Java to determine security policy of the application, that is
actions which are permitted to perform in an application.
12. Private is key word in Java to determine fields and methods which can be directly
accessed only from the class, where they are defined.

39
4. Component Model

Listing 4.4 shows an example of Java class and its fields declared on
lines 4 and 7, its method on line 10. That class does not have defined
constructor explicitly, therefore a default one is defined for it.
Wile using reflection it is possible to for example access and manip-
ulate this class, its fields and constructors during runtime. Listing 4.5
shows an example of such manipulation with this class. On line 5, all
declared fields are retrieved. On line 7 we are iterating over this array of
all declared fields, retrieving the name of the field, its annotation Page
if exists, information whether the field is accessible, and its generic type.
On line 20, there is a demonstration of a way of creating new instances
of classes.

1 public c l a s s S h o w c a s e R e f l e c t i o n C a p a b i l i t i e s {
2
3 public s t a t i c void main ( S t r i n g [ ] a r g s ) throws
InstantiationException , IllegalAccessException {
4
5 Field [ ] declaredFields =
TestGoogleTranslate . class . getDeclaredFields () ;
6
7 for ( F i e l d i : d e c l a r e d F i e l d s ) {
8 S t r i n g name = i . getName ( ) ;
9 Page a n n o t a t i o n = i . g e t A n n o t a t i o n ( Page . c l a s s ) ;
10 boolean i s A c c e s s i b l e = i . i s A c c e s s i b l e ( ) ;
11 Type type = i . getType ( ) ;
12
13 System . out . p r i n t l n ( name ) ;
14 System . out . println ( annotation ) ;
15 System . out . println ( isAccessible ) ;
16 System . out . p r i n t l n ( type ) ;
17 System . out . println () ;
18 }
19
20 TestGoogleTranslate instance =
TestGoogleTranslate . class . newInstance ( ) ;
21 System . out . p r i n t l n ( i n s t a n c e ) ;
22 }
23 }

Listing 4.5: Java Reflection example.


List of Java Reflection features is not completed with these few ones
described, but these are almost all, which were used in the implemen-

40
4. Component Model

tation. Moreover one another Java reflection feature is utilized in the


implementation model, which is quite fundamental, and that is Java
Dynamic Proxies.

Java Dynamic Proxies


Firstly, we need to define Proxy pattern. Formally, it can be defined as
a pattern that provides a surrogate for another object to control access
to it.
A class diagram for this pattern is shown on Figure 4.4. Both Proxy
and RealSubject classes implement a common interface Subject. Hence
when a RealSubject instance is needed, the Proxy instance can be used
instead. Usually, Proxy instance contains reference to the RealSubject,
and dispatches the method invocations to it [39].

Figure 4.4: UML Class diagram for Proxy Pattern.

There are several reasons for creating a surrogate object, and then
the names of the proxies are inferred from this reasons; for example it
is created to control access to a network resources (Firewall Proxy), it
can be created to provide temporary storage for results of expensive
operations (Caching Proxy), or to act as local representative for an
object that does run in the same address space (Remote Proxy), in the
case of Java language, in the same JVM.
Java Dynamic Proxies is a mechanism for creating a Proxy object
at runtime, that implements an interface, or multiple interfaces, and
forwards methods invocations to a specified class. They are created as
stated in the previous section with use of Java Reflection API. The

41
4. Component Model

class diagram for Java Dynamic Proxy (Figure 4.5) differs a little
from the general Proxy class diagram, because it is supplemented with
InvocationHandler class. Its purpose is to respond to any method calls
on the Proxy; it is the way of declaring what Proxy has to do before
invoking method on the real object [39].
An example of the Java Dynamic Proxies use case is creating dynamic
mock objects for unit testing.

Figure 4.5: UML Class diagram for Java Dynamic Proxy Pattern.

Java Generics
Java Generics is a feature added to Java language in version 1.3. Its
main purpose is to enhance type-safety. Consider following Listing 4.6,
which demonstrates the problems, when not using Java Generics.
The class Drawer enables to add any object to it, because its field
is of the Object type, which is the super type of all Java objects.
The main method of the class ShowcaseGenericProblems is compiled
without problems, however, when running, ClassCastException Java
exception is thrown because of line 20, where we are trying to cast
an object of type String to an object of type Object. This is just an
artificial example, but similar problem can easily occur in real-world
examples. The main problem is that it is not caught at compile time,
but it is exposed during runtime.
Listing 4.7 solves this problem by using of Generics.
GenericDrawer has generic type T, which can be supplemented by

42
4. Component Model

any type, and the return value of method getItem is also of the generic
type T. In the main method of the class GenericsSolution, we are per-
forming the same scenario as in previous example, only the instantiation
of the class Drawer uses generics now. Note that is not possible to even
compile GenericsSolution class, we get the error message "Cannot
cast from String to Integer". The result is expected and desired as we
want to catch this type of errors during compile time.

1 public c l a s s GenericDrawer<T> {
2
3 private T item ;
4
5 public void addItem (T item ) {
6 t h i s . item = item ;
7 }
8
9 public T g e t I t e m ( ) {
10 return t h i s . item ;
11 }
12 }
13
14 public c l a s s G e n e r i c s S o l u t i o n {
15

16 public s t a t i c void main ( S t r i n g [ ] a r g s ) {


17
18 GenericDrawer<S t r i n g > drawer = new
GenericDrawer<S t r i n g >() ;
19 drawer . addItem ( " pen " ) ;
20

21 I n t e g e r pen = ( I n t e g e r ) drawer . g e t I t e m ( ) ;
22 }
23 }

Listing 4.6: Example demonstrating type-safety problem when not using


Java Generics.

1 public c l a s s Drawer {
2 private Object item ;
3
4 public void addItem ( Object item ) {
5 t h i s . item = item ;
6 }
7
8 public Object g e t I t e m ( ) {

43
4. Component Model

9 return t h i s . item ;
10 }
11 }
12
13 public c l a s s ShowcaseGenericProblems {
14
15 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
16
17 Drawer drawer = new Drawer ( ) ;
18 drawer . addItem ( " pen " ) ;
19
20 I n t e g e r pen = ( I n t e g e r ) drawer . g e t I t e m ( ) ;
21 }
22 }

Listing 4.7: Example of solving type-safety problem from Listing 4.6


with using of Java Generics.

Service Provider Interface


Service Provider Interface (SPI) is a mechanism to create modular,
plug-in architectures13 which are easy to maintain. For example an
upgrade of one part should not affect whole application.
In Java environment, SPI is a set of public interfaces and abstract
classes which defines a service contract. Service provider than has to
implement these interfaces, and hence also this contract to fetch its
functionality into the application. The exact procedure looks as [41]:
1. The desired functionality which we want to add is packed in a
JAR14 file and is on the application classpath15 ;

2. You have to identify the provided service by placing a file into the
directory where the sources of your application are, and under
it to the directory /META-INF/services, which contains a fully
qualified service name16 .

13. An architecture which allows to add functionality by adding to it small modular


applications, so called plug-ins.
14. The type of archive in which a Java applications are distributed.
15. It is a parameter to tell JVM where classes are located.
16. A name which is complete in a sense that it contains all names in the sequence
above and the name itself, an example is java.lang.String [42].

44
4. Component Model

4.3.2 Integration with existing Frameworks


It is always a good practice to not to reinvent a wheel by implementing
the whole functionality from the beginning. When creating a new project,
utilize already implemented functionality from other frameworks. What
frameworks, and how the created component model utilizes them, is
described in this section.

WebDriver
WebDriver automation tool is already mentioned in the section 3.2. In
the created abstract model, it will be the main automation tool, in other
words, it will be used to make interactions with the browser.
Currently, Arquillian Graphene is used to obtain an instance of
WebDriver, which is subsequently injected into the test object.
To instruct WebDriver what web page element we want to com-
municate with, it uses already seen mechanism of WebElement. For
example line 4 at Listing 4.3 declares such a WebElement by specifying
the XPath of the particular element which is in that example string
//input[@type=’submit’].
XPath is a way of navigation in an XML document, and the structure
of all web pages is also connected with their Document Object Model
(DOM) which is a tree model of all web page elements, constructed in
an XML syntax. This particular string locates a submit button. There
are also other ways of locating web elements, such as CSS selectors.

WebDriver root mechanism What is particularly utilized, is the


way of locating nested elements of the particular web element. Listing
4.8 shows demonstration of the nested elements.
A HTML code of two components can be seen, particularly RichFaces
calendars. Note that the HTML structure of that two components is
the same, only values of attribute id are unique.
The value of id is, however, generated randomly, and differentiates
from one rendering to another. That is the reason why can not rely
only on locating according to id value, but there has to be employed
locating according to other characteristics, for example CSS class, or
the position in the DOM tree.
Based on the research, I discovered that the only thing which de-

45
4. Component Model

termines the particular component unambiguously is its root element


(lines 1 and 12).
We can reference from this root other component’s parts. It is possible
because of WebDriver root mechanism which is shown in Figure 4.6.
It shows two approaches of locating WebElement, firstly when locating
from WebDriver object elements with class nice, two elements are found
(blue marked). When locating the first Root 2 element, and from it
elements which have class nice, only one element is found (red marked).

Figure 4.6: WebDriver way of locating elements.

When taking into consideration the listings 4.8 again, referencing


an img element with class rf-cal-btn from its root element <span
id="j_idt6:calendar1"> (line 1), the image (line 5) from the first
calendar will be selected, not the second one (line 16), even though it
has the same class.
This is used in component model to access different parts of the
components. For example the above mentioned image is a trigger which
has to be clicked on in order to show a calendar in a pop-up panel.
Hence each component needs to have set root, before any action
can be taken with it. Each component’s interface therefore needs to
extend defined Component interface, which contains method setRoot,
and therefore forces a user to implement that method.

46
4. Component Model

1 <span i d=" j _ i d t 6 : c a l e n d a r 1 ">


2 <span i d=" j _ i d t 6 : j _ i d t 9 P o p u p " s t y l e=" white−s p a c e :
nowrap ; ">
3 <i n p u t c l a s s=" r f −c a l −i n p " i d=" j _ i d t 6 : j _ i d t 9 I n p u t D a t e "
name=" j _ i d t 6 : j _ i d t 9 I n p u t D a t e "
4 r e a d o n l y=" r e a d o n l y " s t y l e=" v e r t i c a l −a l i g n : middle ; "
type=" t e x t " />
5 <img a l t=" " c l a s s=" r f −c a l −btn "
i d=" j _ i d t 6 : j _ i d t 9 P o p u p B u t t o n "
6 s r c=" path / toImage / c a l e n d a r I c o n . png "
7 s t y l e=" v e r t i c a l −a l i g n : middle " />
8 .
9 .
10 .
11 .
12 <span i d=" j _ i d t 6 : c a l e n d a r 2 ">
13 <span i d=" j _ i d t 6 : j _ i d t 1 0 P o p u p " s t y l e=" white−s p a c e :
nowrap ; ">
14 <i n p u t c l a s s=" r f −c a l −i n p " i d=" j _ i d t 6 : j _ i d t 1 0 I n p u t D a t e "
name=" j _ i d t 6 : j _ i d t 1 0 I n p u t D a t e "
15 r e a d o n l y=" r e a d o n l y " s t y l e=" v e r t i c a l −a l i g n : middle ; "
type=" t e x t " />
16 <img a l t=" " c l a s s=" r f −c a l −btn "
i d=" j _ i d t 6 : j _ i d t 1 0 P o p u p B u t t o n "
17 s r c=" path / toImage / c a l e n d a r I c o n . png "
18 s t y l e=" v e r t i c a l −a l i g n : middle " />
19 .
20 .
21 .
22 .

Listing 4.8: Web page fragment demonstrating two components -


calendars - at one page.

Arquillian Drone
After the creating a prototype for the first selected component, calendar
(its implementation in Listing 4.9), the usage of this component in the
test looked like Listing 4.10.
The Calendar component from listing has two fields, one annotated
with Root annotation, which represented the field for later setting of
the actual root, and the second annotated with annotation FindBy with

47
4. Component Model

value according to which the element was inferred from component’s


root. To use the component in the test, the tester had to initialise the
component first with created Factory class, and secondly set the actual
root, when the page was loaded, because only then the actual root can
be located.

Initialisation of components The problem was to initialize com-


ponent properly. The components fields annotated with annotation
FindBy needed to recognize the actual root by which they were inferred.
This made an obligation to at first locate the actual root and to in-
ject WebDriver and the root to the Factory class, which can properly
initialise particular annotated fields with use of Java Reflection.
We wanted to avoid this obligation. It was resolved with use of Java
Dynamic Proxies (see section 4.3.1). So when initialising the component,
instead of injecting the real instances of WebElements, Dynamic Proxies
objects are inserted, which invocation handlers forward all method
invocations to the real WebDriver object.
More comprehensive will be probably the study of the Factory class,
and its methods. Appendix B shows the fragments of the Factory class,
the most important method, initializeComponent. This method is
generic (see section 4.3.1), and can initialise any class which extends
AbstractComponent class, it is a constraint to avoid initialising classes
which are not components.
With the use of method instantiateComponent, whose internal
implementation is using Java Reflection (see section 4.3.1), the given
component is instantiated, in other words a new object is created from
the given class.
In next the steps, all declared fields and subsequently all annotations
of given field are retrieved with the use of Java Reflection, and iterated
over to initialise root element and other fields with Java Dynamic Proxy
objects. The initialisation of root element begins on line 17, we are
creating new Proxy, and assigning to it invocation handler class. This
method invoke will be called every time when any method will be called
on the root element. In that method we retrieve the actual root, which
should have already been set to the rootReference by the time that
the method is invoked.
Similar proxy objects are injected into fields annotated with FindBy

48
4. Component Model

annotation17 , with the difference that it finds the actual WebElement


from the root.

1 public c l a s s CalendarImpl {
2
3 @Root
4 private WebElement r o o t ;
5
6 @FindBy ( c s s = " img : nth−of −type ( 1 ) " )
7 private WebElement showCalendarButton ;
8
9 public void showCalendar ( ) {
10 showCalendarButton . c l i c k ( ) ;
11 }
12 }

Listing 4.9: First Calendar component prototype of the implementation.

1 public c l a s s TestPageWithCalendar {
2

3 private CalendarImpl c a l e n d a r ;
4
5 @BeforeClass
6 public void i n i t C a l e n d a r ( ) {
7 calendar =
Fa ctor y . i n i t i a l i z e C o m p o n e n t ( CalendarImpl . c l a s s ) ;
8 }
9
10 @BeforeMethod
11 public void lo adT estPag e ( ) {
12
13 webDriver
14 . g e t ( " h t t p : / / l o c a l h o s t : 8 0 8 0 / myTestApp/ c a l e n d a r . j s f " ) ;
15
16 c a l e n d a r R o o t = webDriver
17 . f i n d E l e m e n t (By . xpath ( " // td [ @ c l a s s =’ e c o l 1 ’ ] " ) ) ;
18 calendar . setRoot ( calendarRoot ) ;
19 }

17. Note that it is standard annotation of WebDriver, so it will be good recognized


by community.

49
4. Component Model

20

21 @Test
22 public void t e s t C a l e n d a r S e r v i c e ( ) {
23 c a l e n d a r . showCalendar ( ) ;
24 }
25
26 }

Listing 4.10: Usage of first calendar implementation.

The next problem was that demonstrated using of calendar compo-


nent is clumsy, because the initialisation and the setting of the root will
be repeated for every component, it is worth to automate it, to enhance
created framework usability.
Therefore we decided to utilize again FindBy annotation, so that
the calendar component will be annotated by FindBy annotation, which
will provide information about the position of the root element on the
tested page.
We needed to discover a mechanism which will perform this auto-
matic discovery of FindBy annotations.

Drone SPI Arquillian provides a way to manage this by providing


SPI (see section 4.3.1) for enriching the test, which is a way to inject
various dependencies into the test object during runtime.
I just needed to provide an implementation for that SPI. Appendix
C.1 shows some important fragments of this implementation. With
the use of reflection it initialises at first fields annotated with FindBy
annotation, it can be either components, then also the root is set to that
component, or it can be other elements which we need to interact with.
Secondly, the fields with Page annotation are initialised, it is support for
Page Objects pattern (see section 4.2.1), so you can use various pages
in the test. These pages can contain other components, and the page
object and its parts are properly initialised by Drone extension.
Arquillian Drone was also used in functional tests for the created
component model.

50
4. Component Model

4.4 Component Case Studies

Designing a good API is complicated, because it is not possible to


meet all user’s requirements. To determine whether an API is good,
we firstly have to realise what is the objective of creating an API. I
would like to provide the users of our API with a way to easily assemble
their application with use of our API, that this operation of assembling
will be easy and will avoid debugging and reading source code, and
furthermore will be understandable for majority of developers. An API
is also created when we want to achieve distributed development of our
application [43].

Good API design First of all, when creating an object oriented (OO)
API, all the OO principles, like encapsulating what varies, favouring
composition over inheritance, program to interfaces not implementations,
do not call us we call you [39], need to be followed to be successful.
However, it is not sufficient for creating an API, it can be sufficient for
creating an application with use of that API.
Jaroslav Tulach, a founder and initial architect of NetBeans IDE,
and currently the development lead advises to keep in mind following
principles when creating an API [43]:
You have to develop a trusting relationship between you and other
programmers, you have to convince them that you are able to produce
and maintain stable API. In practice it can means to maintain backward
compatible API, which is an API which when evolves, the older contract
of the API remains the same, while new functionality is added. To be
more specific, when implementing an interface in Java, it can not happen
that new methods with new releases will be added to that interface, as
it would break the whole code, because the implementations would not
contain the new methods.
It is important to be use case oriented. It is not possible to know all
API users, and therefore their needs. Therefore the solution is to be use
case oriented, what means to work with vision of users’ actions. The
starting point of any design should be answering the questions: Why ?
What ? How ?
That is why we started with possible use cases of future components.
Their can be clearly viewed from Unified Modeling Language 2 diagrams

51
4. Component Model

(UML 2), such as Use Case diagram18 , and Sequence diagram19 .


In following sections we describe such diagrams for three created
components, Autocomplete (section 4.4.1), Table (section 4.4.2), and
Calendar (section 4.4.3).

4.4.1 Autocomplete component

Figure 4.7: RichFaces Autocomplete component.

Autocomplete component (Figure 4.7) represents an input into which,


when a user starts to write, a box with suggestions is provided. From
this suggestions the user can choose either by mouse or by keyboard.
Upon choosing one of the suggestions, the input will be filled with it.
The user can also continue writing.
Figure 4.8 shows Use Case diagram, which captures possible use
cases of the Autocomplete component. Individual use cases are self
descriptive, after all that is their intention, just to note that the label
«include» means, that the included use case needs to be performed at
least once in order to perform the use case which is performing inclusion.
In the appendix D we can see Sequence diagram for Autocomplete
component. It shows a possible test scenario, or in other words, some of
the use cases ordered in time.

1. The tester at first retrieves expected data from a database, and


then fills in the input with prefix of word, which also returns all
available suggestions.

18. Use Case diagram, http://en.wikipedia.org/wiki/Use_case


19. Sequence diagram, http://www.ibm.com/developerworks/rational/
library/3101.html.

52
4. Component Model

Figure 4.8: Autocomplete component Use Case diagram.

2. Then he can fill in the input with prefix of word, which should
not have any suggestions, and assert the expected state.

3. The last Autocomplete behavior he is testing is autocompletion


with some suggestion. This performs two times, and then once
filling in the input value with no suggestions.

4. After fetching all selected suggestions he will verify that only


values, which were selected from suggestions were retrieved.

This is a simple example of the use of a model for component


Autocomplete. More real-world example is provided in section 4.5
An API for this component was created with considering these two
diagrams. Its key behaviors are:

• Autocomplete component has generic type, this type determines


what kind of suggestions it can provide, for example plain text,
or tables with pictures;

• user of this API will be able to get all available suggestions, or


just the specific suggestions;

53
4. Component Model

• autocomplete with specified suggestion;

• clear the input;

• set separator, which separates selected suggestions, or to use the


default one;

• get all values from the input, which were filled in with autocom-
pletition from a suggestion list;

• suggestion is encapsulated in the class Suggestion

For more please see the generated Javadoc documentation.

4.4.2 Table component

Figure 4.9: RichFaces Table component.

Data table component (Figure 4.9) represents an HTML table.


HTML table supports creating of headers and footers, connecting cells
into one, and rendering not only a textual information into the cells.
Cells can contain for example pictures, inputs or other HTML elements.

54
4. Component Model

Figure 4.10 shows possible use cases of the Table component. The
component should provide a way to get any part of the table, like
particular cell, column or row and also their content (e.g. Get Any
Part of Table, Get Table Header/Footer, Get Content of Table Part).
It should also be possible also to find parts of the table according to
some filter function (Find Parts of Table, Determine Which Parts of
Table). The last example of functionality is a mechanism for iterating
over multiple table pages.
Appendix E.1 shows possible test scenario of table component. With
regards to Figure 4.9, typing values into the input nested in the header
causes triggering of filter function, which subsequently renders only rows
which conform the filtering function.
The test scenario is based on this functionality, therefore the first
step is to create a table with particular columns, get the input element
from the first header cell, type a string into that input, and iterating
over rendered filtered rows, to assert that they contain only values which
agree with the filled in value.

Figure 4.10: Use Case diagram of the Table component.

The Table component is indeed the most complex component, as


it has to deal with the fact that the cells may contain any possible
element: text values, numbers, pictures, or other elements for which the

55
4. Component Model

API was created, like for example Calendar component or mentioned


Autocomplete component.
The hierarchy of Table component (Class diagram in Figure 4.11) con-
sists of base class TableComponent, their parts: Cell, Column, and Row’s
special cases: Header and Footer. TableComponent1 and
TableComponent6 extends the TableComponent, as it is not possi-
ble to define base class with variable number of generic parameters,
and therefore each number of columns has to have its own specific
class. As it can be seen in the example, 6 columns table is repre-
sented by TableComponent6 and so on. Cell is a special case of generic
ComponentsContainer which can contain other NestedElements.
RowFunction, ColumnFunction and CellFunction defines one method,
accept (inspired by the Command pattern 20 ). This interfaces should
be implemented by the end user of the component, to determine filtering
function for cells, rows and columns, which instances are then passed to
e.g. Table function findCells.

Figure 4.11: Class diagram of the Table component.

20. Command pattern, general information at http://en.wikipedia.org/wiki/


Command_pattern.

56
4. Component Model

4.4.3 Calendar component


Calendar component (Figure 4.1) serves for selecting particular date,
and then for showing the selected date.
The Use Case diagram from Figure 4.12 may at first sight appear
that lot of possible calendar’s behaviour is missing, however, the API
should be abstract enough to include all type of implementations. This
particular diagram is for the most abstract calendar, as with all calendars
it should be possible to select the date and then retrieve the selected
date.

Figure 4.12: Calendar component Use Case diagram.

To implement more specific calendars, a user can extend this abstract


calendar and provide API for his desired calendar implementation. I did
it, and implemented the API for calendar which when is invoked is
rendered in a popup, and the selected date is shown in the input. This
type of calendar is for example implemented in RichFaces and JQuery
UI (see the section 4.1.1). Its Use Case (Figure 4.13) diagram is richer
in number of behaviors.
The Sequence diagram for Calendar Popup component can be found
in appendix F. It is again demonstrating an example of a typical in-
teraction with a particular component, in this example simultaneously
with two calendars. So for example a tester can:
1. Set the next day date on the first calendar, that would represent
an start time of some activity.

2. set the date, for example a month and two days after current
date to the second calendar, that would represent an end of the
activity.

57
4. Component Model

Figure 4.13: Popup Calendar component Use Case diagram.

3. Get the selected dates from both calendars, and verifies that
expected dates were selected.

4. Then he can go to the current date on the first calendar and to


the date of previous day on the second one.

5. Finally he verifies that an error message was rendered, because


the beginning date can be not after the end date of the activity.
The Calendar Popup component encapsulates these possible interac-
tions between the user and the component itself:
• user of the component will be able to show and hide the calendar,
that is, render it in the popup mode and then hide it to show
only the input with selected date;

• it will be possible to clean the input;

• get selected time unit;

• the time unit is type-safe encapsulation for day, week, month


and year;

• select the previous or next time unit;

58
4. Component Model

• select particular DateTime21 ;

• the time unit is encapsulated in the class TimeUnit, and other


units like CalendarDay, CalendarWeek, CalendarMonth and Cal-
endarYear extend it.

4.5 Real Deployment


Previous examples of component model usages were mostly artificial. To
see its benefits clearly I decided to create a simple showcase application
which will be tested with use of Arquillian Drone and the implemented
component model.
This chapter describes mostly only key attributes of that application
and its tests, the benefits of the chosen approach, and extends also
slightly into the browser compatibility topic. The full code examples,
either of the showcase application or its tests can be found on the
attached CD together with implementation. The step by step manual,
which describes the obtaining and building the showcase application,
can be found at appendix H.

4.5.1 Showcase application

To begin with the application, its intent is to imitate real-world example


of an application. Only a very small part of it. However, complex
enough to mime a real application. For this purpose I created just one
page which should represent an order form for a service. It contains all
described components from sections 4.4.1, 4.4.2, and 4.4.3 and also other
implemented components, which were not described in this textual part
of the thesis (Validation Component, Check-box Component, Number
Spinner Component). It is implemented in RichFaces web framework
(see the section 4.1.1).

21. API for Calendar uses Joda Time library, which enhances the standart
java.util.Date and java.util.Calendar libraries, and improves flaws in their desing.
Available at http://joda-time.sourceforge.net/.

59
4. Component Model

Figure 4.14: Screenshot from showcase application.

4.5.2 Functional Tests


The best way how to showcase differences between writing tests with use
of component model and without using it is to show both approaches to
the same test scenario. The common test scenario is verification if data
is filled in correctly, then after clicking on the submit button a proceed
button is shown.
It consists from these steps:

1. Fill all inputs with correct data, that means, data which pass
length and other validation criteria. There are five ordinary
inputs, one with auto-complete function and two calendars, which
need to be completed in order to proceed in the service ordering.

2. Select the service from the third row of the table by selecting
the check-box and filling in the number spinner input value 4.

3. Clicking on the submit button.

4. Asserting that no error messages were rendered and that proceed


button was shown.

Appendixes I and J shows these functional tests, without using


of component model and with use of it respectively. They are both

60
4. Component Model

Arquillian Drone tests, which uses WebDriver as test harness (see the
section 2.2.1).
For the purpose of demonstrating only differences of writing tests
with use of component model API and without it ,some important
parts needed for executing these tests are omitted, for example, the
need of initialising the FindBy annotations for listing which does not
use component model, or methods which take care of deployment of
application to test.

Benefits of using component model


Saved code lines The first noticeable difference is the number of
lines which each listing takes. Let’s aim at bodies of the test methods.
For the listing which does not use component model, it takes 54 code
lines, and for the listing which use component model, it is 33 lines (the
start of the body is test method declaration and the end of the body is
closing curly bracket).
Those 21 lines were saved firstly because the functionality was
encapsulated into the component model, and now it is enough to call
the functionality from there. An example of this are lines 69 to 76 of
Listing I. There is an implicit waiting for client browser to render the
calendar. Similar waiting is implemented in the component model, and
therefore Listing J is freed of this waits. One can argue that these waits
can be extracted into one method and called when needed. However, the
same logic applies for the example which use component model, there
are also parts which can be extracted, However, in order to establish
equal conditions there were no extractions in both examples. Other
encapsulated elements in component model are WebElement objects, as
in lines 30-34 of Listing I, these are automatically defined in component
model, as their definition is same for all calendars.

Encapsulated HTML structure If there will be only saved lines


benefit, it would be too little addition to tests maintenance, indeed
important, but not as much as the main advantage of using of component
model. The main benefit is that an HTML structure of the tested page
is encapsulated in the component model (lines 21, 30, 33, 36, 39, 48
in Listing I), which enables better robustness of tests. Should this
structure change in the future, the only place where change will have

61
4. Component Model

to be introduced, will be the implementation of the component model,


which is common for all application written in the same component web
framework, like for example in RichFaces.

Enhanced test readability The test readability is is enhanced when


using component model. The test scenario of Listing J is more compre-
hensive. Suppose for example lines 81-82 of Listing I, and line 52 of
Listing J. Both examples are selecting the current day on the calendar,
but in a very different way. There are similar examples of this enhance-
ment, match lines 64-66 of Listing I with lines 49-50 of Listing J or lines
98-100 with line 64 of listings in the same order as previously.

Enhanced re-usability and accessibility By using higher-level ab-


straction, developers are equipped with tool which enhances re-usability
of tests. It also enables them to develop tests in shorter time, because
they will utilize API’s functionality. It may lead to the state when
developing functional tests would not be tedious and cumbersome, but
would be straightforward.

Encapsulated browser interoperability This benefit is not no-


ticeable from the two listings, but the browser interoperability can
be encapsulated in the component model. That means, when it is
needed to write browser specific code, it is not necessary to write
it in the tests any more. Browser specific code is needed because of
different browser engines for JavaScript. Because of this fact, it is of-
ten necessary to alter test method according to what browser it is
tested on. This information can be retrieved from the running type of
WebDriver object and encapsulated in component model, so should the
test requirements change from using of one browser version to another,
the change will be introduced only at component model, not in tests.

62
5 Conclusion
The aim of this thesis was to explore and to describe modern trends
in testing enterprise web applications. After the research, tools for
automated testing of these applications were selected and compared.
The main focus was on maintainability and implementation of tests
developed by the tools and their usage in the systems of continuous
integration. Based on this analysis, I was supposed to provide high level
application programming interface that could be used in testing the
component based web application user interfaces.
The major contribution of this thesis is the created high level API,
as it improves maintainability of tests by increasing their readability, by
more accurately reflecting the intention of a test script. I also proved
that employing a created API can save valuable code lines of tests in
some cases up to 39%. Use of created API also increases the robustness
of tests, by encapsulating the structure of web pages in the created
model. This reduces the scope for introducing an error in the test since
any change in the structure of web pages will appear in one place.
I have designed API for nine web components, including highly
complex one, table. Programmed implementation of the API for web
framework RichFaces is currently used mainly for thesis presentation
purposes. Based on the analysis of automation tools for testing the UI, I
chose Arquillian Drone instrument, and I I managed to integrate it with
API. By implementing this integration I was able to learn lot of Java
specific frameworks and APIs, for example Reflection API, SPI and Java
Dynamic Proxies. I was also able to grasp and employ object oriented
design patterns, for example Proxy pattern, Page Objects pattern and
Command pattern. This integration improves the usability of the API,
and by the fact that it is based on known and by a wide community of
developers respected instruments, it is also ready for being adopted by
that community. The created solution is suitable for use in the enterprise
sector, and its benefits can help reduce costs needed for development,
testing and maintaining software.
There are several possible extensions of this thesis, among others it
includes designing APIs for other web components and complete the
outlined implementation for RichFaces web framework. The intention is
to open source this project, to enable the community around UI testing

63
5. Conclusion

to improve and contribute to this project. As an open source project it


will provide an opportunity for other web frameworks to implement the
API.

64
Bibliography
[1] James Bach. Test Automation Snake Oil. http://www.satisfice.
com/articles/test_automation_snake_oil.pdf, 1999. [Online;
accessed 13-May-2012].

[2] Dale H. Emery. Writing Maintainable Automated Accep-


tance Tests. http://dhemery.com/pdf/writing_maintainable_
automated_acceptance_tests.pdf, 2009. [Online; accessed 14-
May-2012].

[3] Bill Hetzel. The Complete Guide to Software Testing, volume 2.


Wellesley, Mass. : QED Information Sciences, 1988.

[4] Ron Patton. Software Testing. Sams Publishing, 2005.

[5] Cem Kaner, Jack Falk, and Hung Nguyen Q. Testing Computer
Software, volume 2. Van Nostrand Reinhold, 1993.

[6] 829-2008 - IEEE Standard for Software and System Test


Documentation. http://ieeexplore.ieee.org/servlet/opac?
punumber=4578271, 2008. [Online; accessed 13-May-2012].

[7] Douglas Hoffman. Test Automation Architectures: Planning


for Test Automation. http://softwarequalitymethods.com/
Papers/autoarch.PDF, 1999. [Online; accessed 13-May-2012].

[8] Wikipedia. Software testing — Wikipedia, The Free Encyclope-


dia. http://en.wikipedia.org/w/index.php?title=Software_
testing&oldid=492035622, 2012. [Online; accessed 12-May-2012].

[9] Selecting a development approach. http://www.


cms.gov/Research-Statistics-Data-and-Systems/
CMS-InformationTechnology/SystemLifecycleFramework/
downloads//SelectingDevelopmentApproach.pdf, 2005. [On-
line; accessed 12-May-2012].

[10] Boris Beizer. Software Testing Techniques, volume 2. Van Nostrand


Reinhold Co, 1990.

65
5. Conclusion

[11] Cynthia Lovin and Tony Yaptangco. Best Practices: Enterprise Test-
ing Fundamentals. http://www.dell.com/downloads/global/
power/ps1q06-20050111-Lovin.pdf, 2006. [Online; accessed 13-
May-2012].

[12] Yoonsik Cheon and Gary T. Leavens. A Simple and Practical


Approach to Unit Testing: The JML and JUnit Way. In ECOOP
2002 - Object-Oriented Programming, volume 2374 of Lecture Notes
in Computer Science, June 2002.

[13] Complete Automation of Unit Testing. http://opuntia.cs.utep.


edu/utjml/utest.html, 2006. [Online; accessed 19-May-2012].

[14] Eclipse - The Eclipse Foundation open source community website.


http://www.eclipse.org/, 2012. [Online; accessed 13-May-2012].

[15] Welcome to NetBeans. http://netbeans.org/, 2012. [Online;


accessed 13-May-2012].

[16] Michael Minella. The Concept of Mocking. http://java.dzone.


com/articles/the-concept-mocking, 2008. [Online; accessed 13-
May-2012].

[17] Kent Beck. Test-Driven Development by Example. Addison Wesley,


2003.

[18] Steve Freeman, Nat Pryce, Tim Mackinnon, and Joe Walnes. Mock
Roles, not Objects. http://www.jmock.org/oopsla2004.pdf,
2004. [Online; accessed 13-May-2012].

[19] Wikipedia. Application programming interface — Wikipedia, The


Free Encyclopedia, 2012. [Online; accessed 13-May-2012].

[20] Dariusz Cieslak. What’s Wrong With Automated In-


tegration Tests? http://blog.aplikacja.info/2012/03/
whats-wrong-with-automated-integration-tests/, 2012. [On-
line; accessed 19-May-2012].

[21] J2EE Containers. http://docs.oracle.com/javaee/1.4/


tutorial/doc/Overview3.html. [Online; accessed 13-May-2012].

66
5. Conclusion

[22] Julien Dubois. In-Container Testing with JU-


nit. http://www.oracle.com/technetwork/articles/
server-side-unit-tests-096611.html. [Online; accessed
13-May-2012].
[23] Rick Mugridge, Mark Utting, and David Streader. Evolving Web-
Based Test Automation into Agile Business Specifications. www.
mdpi.com/1999-5903/3/2/159/pdf, 2011. [Online; accessed 13-
May-2012].
[24] Kent Beck. Extreme Programming Explained: Embrace Change.
Addison–Wesley, 1999.
[25] Paul M. Duvall, Steve Matyas, and Andrew Glover. Continuous
Integration: Improving Software Quality and Reducing Risk. Addi-
son–Wesley, 2007.
[26] IT Definitions and Glossary. http://www.gartner.com/
technology/it-glossary/, 2012. [Online; accessed 13-May-2012].
[27] Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt,
Robert Mee, and Randy Stafford. Patterns of Enterprise Applica-
tion Architecture. Addison Wesley, 2002.
[28] OWASP Enterprise Application Security Project - OWASP.
https://www.owasp.org/index.php/OWASP_Enterprise_
Application_Security_Project, 2010. [Online; accessed
13-May-2012].
[29] Carlos Delano Buskey. A Software Metrics Based Approach to
Enterprise Software Beta Testing Design, 2005.
[30] Rick Hower. Web Test Tools, 2012. [Online; accessed 14-May-2012].
[31] Browser Statistics. http://www.w3schools.com/browsers/
browsers_stats.asp, 2012. [Online; accessed 14-May-2012].
[32] Aslak Knutsen. Drone. https://docs.jboss.org/author/
display/ARQ/Drone, 2012. [Online; accessed 14-May-2012].
[33] Geb - Very Groovy Browser Automation. http://www.gebish.
org/. [Online; accessed 14-May-2012].

67
5. Conclusion

[34] Lukáš Fryč. Arquillian Graphene. https://community.jboss.


org/wiki/ArquillianGraphene, 2011. [Online; accessed 14-May-
2012].

[35] Martin Fowler. GUI Architectures. http://www.martinfowler.


com/eaaDev/uiArchs.html#ModelViewController, 2006. [On-
line; accessed 15-May-2012].

[36] Wikipedia. Web application framework — Wikipedia, The Free


Encyclopedia, 2012. [Online; accessed 15-May-2012].

[37] Page Objects. http://code.google.com/p/selenium/wiki/


PageObjects, 2011. [Online; accessed 15-May-2012].

[38] Chapter 3: Architectural Patterns and Styles. http:


//msdn.microsoft.com/en-us/library/ee658117.aspx#
ComponentBasedStyle, 2009. [Online; accessed 15-May-2012].

[39] Eric Freeman, Elisabeth Freeman, Kathy Sierra, and Bert Bates.
Head First Design Patterns. O’Reilly Media, Inc., 2004.

[40] Trail: The Reflection API. http://docs.oracle.com/javase/


tutorial/reflect/index.html. [Online; accessed 15-May-2012].

[41] John O’Conner. Creating Extensible Applications With


the Java Platform. http://java.sun.com/developer/
technicalArticles/javase/extensible/index.html, 2007.
[Online; accessed 15-May-2012].

[42] Martin H. Weik. Computer Science and Communications Dictio-


nary, volume 1. Springer, 2000.

[43] Jaroslav Tulach. Practical API Design: Confessions of a Java


Framework Architect. Apress, 2008.

[44] SeleniumExamples. http://seleniumexamples.com/blog/, 2010.


[Online; accessed 13-May-2012].

68
A Example of UI test verbosity

1 public c l a s s Meetup {
2
3 // d e c l a r a t i o n o f used f i e l d s
4
5 @Test
6 public void l i s t R e s p o n s e s ( ) {
7
8 // open t h e e v e n t page
9 d r i v e r . g e t ( " h t t p : / /www. meetup . com/ " + meetup +
" / calendar / " + event + " / " ) ;
10
11 i f ( d r i v e r . f i n d E l e m e n t (By .
12 xpath ( " i d ( ’ C_document ’ ) / d e s c e n d a n t : : " +
13 " d l [ @ c l a s s =’ s t a t s ’ ] [ 2 ] / dt " ) ) .
14 getText ( ) . e q u a l s ( "Who ’ s coming ? " ) ) {
15 // t h i s e v e n t has not y e t o c c u r r e d
16 listMembers
17 ( " i d ( ’ C_document ’ ) // l i [ d i v [ @ c l a s s=" +
18 " ’ D_attendeeHeader D_yes ’ ] ] " +
19 " // l i [ s t a r t s −with ( @id , ’ member_ ’ ) ] " , " Yes " ) ;
20 listMembers
21 ( " i d ( ’ C_document ’ ) // l i [ d i v " +
22 " [ @ c l a s s =’ D_attendeeHeader D_maybe ’ ] ] " +
23 " // l i [ s t a r t s −with ( @id , ’ member_ ’ ) ] " ,
" Maybe " ) ;
24 listMembers
25 ( " i d ( ’ C_document ’ ) // l i [ d i v " +
26 " [ @ c l a s s =’ D_attendeeHeader D_no ’ ] ] " +
27 " // l i [ s t a r t s −with ( @id , ’ member_ ’ ) ] " , "No" ) ;
28 } else {
29 // t h i s e v e n t i s i n t h e p a s t
30 l i s t M e m b e r s ( " i d ( ’ C_document ’ ) // " +
31 " l i [ s t a r t s −with ( @id , ’ member_ ’ ) ] " ,
" Attended " ) ;
32 }
33 }
34
35 // o t h e r methods i m p l e m e n t a t i o n

Listing A.1: Example of UI test verbocity [44].

69
B Factory class and its methods

1 public c l a s s Fa ctor y {
2
3 public s t a t i c <T extends AbstractComponent> T
i n i t i a l i z e C o m p o n e n t ( C l a s s <T> c l a z z ) {
4 AbstractComponent component =
instantiateComponent ( c l a z z ) ;
5
6 Field [ ] declaredFields = clazz . getDeclaredFields () ;
7

8 fi nal RootReference rootReference =


component . g e t R o o t R e f e r e n c e ( ) ;
9
10 for ( F i e l d i : d e c l a r e d F i e l d s ) {
11
12 Annotation [ ] a n n o t a t i o n s = i . g e t A n n o t a t i o n s ( ) ;
13 f o r ( Annotation j : a n n o t a t i o n s ) {
14
15 i f ( j instanceof Root ) {
16
17 WebElement ro o tE le me nt =
18 ( WebElement )
19 Proxy . newProxyInstance
20 ( WebElement . c l a s s . g e t C l a s s L o a d e r ( ) ,
21 new C l a s s <? >[] { WebElement . c l a s s } , new
InvocationHandler () {
22
23 @Override
24 public Object i n v o k e ( Object proxy , Method method ,
Object [ ] a r g s ) throws Throwable {
25 WebElement r o o t = r o o t R e f e r e n c e . g e t ( ) ;
26 i f ( r o o t == null ) {
27 throw new RuntimeException ( " The r o o t has t o
be s e t c o r r e c t " ) ;
28 }
29 return ( Object ) method . i n v o k e ( r o o t , a r g s ) ;
30 }
31 }) ;
32 }
33 .
34 .
35 i . s e t ( component , r oo t El em en t ) ;
36 .

70
B. Factory class and its methods

37 .
38 .
39 i f ( j instanceof FindBy ) {
40
41 WebElement r e f e r e n c e d E l e m e n t =
42 ( WebElement )
43 Proxy . newProxyInstance
44 ( WebElement . c l a s s . g e t C l a s s L o a d e r ( ) ,
45 new C l a s s <? >[] { WebElement . c l a s s } , new
InvocationHandler () {
46
47 @Override
48 public Object i n v o k e ( Object proxy , Method method ,
Object [ ] a r g s ) throws Throwable {
49 WebElement r o o t = r o o t R e f e r e n c e . g e t ( ) ;
50
51 i f ( r o o t == null ) {
52 throw new RuntimeException ( " You have t o s e t
root element c o r r e c t l y ! " ) ;
53 }
54
55 WebElement myElement = r o o t . f i n d E l e m e n t ( findBy ) ;
56 return method . i n v o k e ( myElement , a r g s ) ;
57 }
58 }) ;
59
60 i . s e t ( component , r e f e r e n c e d E l e m e n t ) ;
61 }
62 }
63 }
64

65 return (T) component ;


66 }
67
68 }

Listing B.1: Factory class with its methods used to initialise given
component.

71
C Test enricher

1 public c l a s s E n r i c h e r implements T e s t E n r i c h e r {
2
3 @Override
4 public void e n r i c h ( Object t e s t C a s e ) {
5
6 // a t f i r s t i n i t i a l i z e findBy a n n o t a t i o n s
7 i f ( R e f l e c t i o n H e l p e r . i s C l a s s P r e s e n t (FIND_BY_ANNOTATION) )
8 {
9

10 initFieldsAnnotatedByFindBy ( testCase ) ;
11 }
12 // i n i t i a l i z e Page o b j e c t s i f t h e r e a r e any
13 i f ( R e f l e c t i o n H e l p e r . i s C l a s s P r e s e n t (PAGE_ANNOTATION) )
14 {
15

16 L i s t <F i e l d > f i e l d s =
ReflectionHelper . getFieldsWithAnnotation (
17 t e s t C a s e . g e t C l a s s ( ) , Page . c l a s s ) ;
18
19 i n i t i a l i z e P a g e O b j e c t F i e l d s ( testCase , f i e l d s ) ;
20 }
21 }

Listing C.1: Implementation of Arquillian Test Enricher SPI.

72
D Sequence Diagram of Autocomplete Com-
ponent

Figure D.1: Autocomplete component Sequence Diagram.

73
E Sequence diagram of Table Component

Figure E.1: Sequence Diagram of Table Component.

74
F Sequence Diagram of Calendar Popup
Component

Figure F.1: Calendar popup component Sequence Diagram.

75
G Omitted Arquillian test configuration.

1 public c l a s s TestMyApp extends A r q u i l l i a n {


2 // used f i e l d s d e c l a r a t i o n
3

4 @Deployment ( t e s t a b l e = f a l s e )
5 public s t a t i c WebArchive d e p l o y ( ) {
6 MavenDependencyResolver r e s o l v e r =
D e p en d e n cy R e s o l ve r s .
7 u s e ( MavenDependencyResolver . c l a s s )
8 . loadMetadataFromPom ( "pom . xml " ) ;
9
10 WebArchive war = ShrinkWrap
11 . c r e a t e ( WebArchive . c l a s s , " f t e s t −app . war " )
12 . a d d A s D i r e c t o r i e s ( Archi vePaths .
13 create ( " templates " ) )
14 . addAsWebResource (new F i l e (WEBAPP_SRC +
" / t e m p l a t e s / t e m p l a t e . xhtml " ) ,
15 Archi vePaths .
16 c r e a t e ( " t e m p l a t e s / t e m p l a t e . xhtml " ) )
17 . addAsWebInfResource (new F i l e (WEBAPP_SRC +
" /WEB−INF/web . xml " ) )
18 . addAsWebInfResource (new F i l e (WEBAPP_SRC +
" /WEB−INF/ f a c e s −c o n f i g . xml " ) )
19 . addAsLibraries (
20 resolver . artifacts
21 ( " org . r i c h f a c e s . ui : " +
22 " r i c h f a c e s −components−u i " ,
23 " org . r i c h f a c e s . core : " +
24 " r i c h f a c e s −c o r e −impl " )
25 . resolveAsFiles () ) ;
26
27 return war ;
28 }
29 }

Listing G.1: Omitted configuration of AUT deployment using of


ShrinkWrap.

76
H Manual for building showcase applica-
tion
To build showcase application, you need to do following:

1. Set-up Java environment properly. It can be done by following


http://docs.oracle.com/javase/7/docs/webnotes/install/
index.html.

2. Set-up Apache Maven according to http://maven.apache.org/


users/index.html.

3. Obtain sources of component model and component model show-


case. They are accessible also from the attached CD.

4. Install the component model, by running following command


from the directory of the component model: mvn clean install
-DskipTests=true

5. Obtain JBoss Application Server 7 to run on it the showcase


application. It can be downloaded from http://www.jboss.org/
jbossas/downloads/. Choose the certified Java EE 6 Full Profile
application server, with version 7.1.1.Final.

6. Unzip the JBoss AS at desired directory and start it by following


the manual in README.txt file in the application server main
directory.

7. Run functional tests for the showcase application by running the


command (your active directory is component-model-showcase)
mvn clean verify -Pjbossas-remote-7
Notes: Showcase functional tests are configured to run currently
on Firefox 10 and worse. It can be configured for any browser,
but currently you should have installed Firefox in order to run
the showcase-functional tests.

77
I Functional test without using of Compo-
nent Model

1 public c l a s s TestWithoutComponentModel extends A b s t r a c t T e s t


{
2
3 @FindBy ( i d = " name " )
4 private WebElement f i r s t N a m e I n p u t ;
5
6 @FindBy ( i d = " lastName " )
7 private WebElement lastNameInput ;
8
9 @FindBy ( i d = " e m a i l " )
10 private WebElement e m a i l ;
11
12 @FindBy ( i d = " a d d r e s s " )
13 private WebElement a d d r e s s ;
14
15 @FindBy ( i d = " c o u n t r y " )
16 private WebElement c o u n t r y ;
17
18 @FindBy ( i d = " company " )
19 private WebElement company ;
20
21 @FindBy ( xpath = " / / ∗ [ @ c l a s s =[ r f −au−itm r f −au−opt
r f −au−f n t r f −au−i n p r f −au−itm−s e l r f −au−opt−s e l ] " )
22 private WebElement i t e m I n S u g g e s t i o n L i s t ;
23

24 @FindBy ( className = " calendarFromPopupButton " )


25 private WebElement calendarFromInvokeButton ;
26
27 @FindBy ( className = " calendarToPopupButton " )
28 private WebElement c a le n d ar T o In v o ke B u tt o n ;
29

30 @FindBy ( c s s = " span [ i d=calendarFrom ]


td [ c l a s s=r f −c a l −c−cnt−o v e r f l o w r f −c a l −today ] " )
31 private WebElement fromCalendarTodayCell ;
32
33 @FindBy ( c s s = " span [ i d=c a l e n d a r T o ]
td [ c l a s s=r f −c a l −c−cnt−o v e r f l o w r f −c a l −today ] " )
34 private WebElement t o C a l e n d a r T o d a y C e l l ;
35
36 @FindBy ( c s s = " t r [ i d=t a b l e : 2 ] i n p u t [ c l a s s=r f −i n s p −i n p ] " )

78
I. Functional test without using of Component Model

37 private WebElement numberSpinnerFromThirdRow ;


38
39 @FindBy ( c s s = " t r [ i d=t a b l e : 2 ] i n p u t [ type=checkbox ] " )
40 private WebElement checkboxFromThirdRow ;
41
42 @FindBy ( i d = " submitButton " )
43 private WebElement submitButton ;
44
45 @FindBy ( i d = " proceedButton " )
46 private WebElement proceedButton ;
47
48 @FindBy ( className = " r f −msg−d e t " )
49 private WebElement e r r o r M e s s a g e ;
50
51 S t r i n g f r o m C a l n e d a r C e l l I D = " calendarFromDayCell " ;
52 S t r i n g t o C a l n e d a r C e l l I D = " c a le nd a r To D ay C el l " ;
53
54 @Test
55 public void t e s t ( ) {
56
57 f i r s t N a m e I n p u t . sendKeys ( " J u r a j " ) ;
58 lastNameInput . sendKeys ( " Huska " ) ;
59 e m a i l . sendKeys ( " random@mail . com " ) ;
60 a d d r e s s . sendKeys ( " Somewhere i n t h e middle . " ) ;
61 c o u n t r y . sendKeys ( " S l o v a k i a " ) ;
62
63 company . sendKeys ( " Red " ) ;
64 assertTrue ( itemInSuggestionList . isDisplayed () ,
65 " The S u g g e s t i o n l i s t s h o u l d be v i s i b l e ! " ) ;
66 itemInSuggestionList . c lick () ;
67

68 calendarFromInvokeButton . c l i c k ( ) ;
69 (new WebDriverWait ( webDriver , 2 ) )
70 . u n t i l (new ExpectedCondition <Boolean >() {
71
72 public Boolean apply ( WebDriver d ) {
73

74 return fromCalendarTodayCell . i s D i s p l a y e d ( ) ;
75 }
76 }) ;
77
78 DateTime today = new DateTime ( ) ;
79 int dayNumber = today . getDayOfMonth ( ) ;
80

79
I. Functional test without using of Component Model

81 webDriver . f i n d E l e m e n t (By . i d ( f r o m C a l n e d a r C e l l I D +
( dayNumber − 1 ) ) )
82 . click () ;
83
84 c a le n da r T oI n v ok e B ut t o n . c l i c k ( ) ;
85 (new WebDriverWait ( webDriver , 2 ) )
86 . u n t i l (new ExpectedCondition <Boolean >() {
87
88 public Boolean apply ( WebDriver d ) {
89
90 return t o C a l e n d a r T o d a y C e l l . i s D i s p l a y e d ( ) ;
91 }
92 }) ;
93
94 webDriver . f i n d E l e m e n t (By . i d ( f r o m C a l n e d a r C e l l I D +
( dayNumber + 3 ) ) )
95 . click () ;
96
97 numberSpinnerFromThirdRow . sendKeys ( " 4 " ) ;
98 i f ( ! checkboxFromThirdRow . i s S e l e c t e d ( ) ) {
99 checkboxFromThirdRow . c l i c k ( ) ;
100 }
101
102 submitButton . c l i c k ( ) ;
103

104 a s s e r t F a l s e ( errorMessage . isDisplayed () ,


105 " There s h o u l d be no e r r o r me ssa ges ! " ) ;
106
107 a s s e r t T r u e ( proceedButton . i s D i s p l a y e d ( ) ,
108 " Proceed button s h o u l d be v i s i b l e i n t h i s moment ! " ) ;
109 }

Listing I.1: Functional test without use of Component Model

80
J Functional test with using of Component
Model

1 public c l a s s TestWithComponentModel extends A b s t r a c t T e s t {


2
3 @FindBy ( i d = " name " )
4 private WebElement f i r s t N a m e I n p u t ;
5
6 @FindBy ( i d = " lastName " )
7 private WebElement lastNameInput ;
8
9 @FindBy ( i d = " e m a i l " )
10 private WebElement e m a i l ;
11
12 @FindBy ( i d = " a d d r e s s " )
13 private WebElement a d d r e s s ;
14
15 @FindBy ( i d = " c o u n t r y " )
16 private WebElement c o u n t r y ;
17
18 @FindBy ( i d = " company " )
19 private AutocompleteComponentImpl<S t r i n g > company ;
20
21 @FindBy ( i d = " calendarFrom " )
22 private CalendarPopupComponentImpl calendarFrom ;
23
24 @FindBy ( i d = " c a l e n d a r T o " )
25 private CalendarPopupComponentImpl c a l e n d a r T o ;
26
27 @FindBy ( i d = " t a b l e " )
28 private T a b l e W i t h S e r v i c e s t a b l e ;
29
30 @FindBy ( i d = " submitButton " )
31 private WebElement submitButton ;
32
33 @FindBy ( i d = " proceedButton " )
34 private WebElement proceedButton ;
35
36 private ValidationComponent v a l i d a t i o n ;
37

38 @Test
39 public void
40 test () {

81
J. Functional test with using of Component Model

41

42 f i r s t N a m e I n p u t . sendKeys ( " J u r a j " ) ;


43 lastNameInput . sendKeys ( " Huska " ) ;
44 e m a i l . sendKeys ( " random@mail . com " ) ;
45 a d d r e s s . sendKeys ( " Somewhere i n t h e middle . " ) ;
46 c o u n t r y . sendKeys ( " S l o v a k i a " ) ;
47

48 company . t y p e S t r i n g ( " Red " ) ;


49 company . a u t o c o m p l e t e W i t h S u g g e s t i o n
50 ( company . g e t F i r s t S u g g e s t i o n ( ) ) ;
51
52 calendarFrom . gotoNextDay ( ) ;
53 c a l e n d a r T o . gotoDateTime (new DateTime ( ) . plusDays ( 4 ) ) ;
54
55 Row row = t a b l e . getRow ( 2 ) ;
56
57 C e l l <NumberSpinnerComponent> c e l l 1 =
row . g e t C e l l ( t a b l e . getColumn3 ( ) ) ;
58 NumberSpinnerComponent numberSpinner =
c e l l 1 . getContent ( ) . get (0)
59 . getValue ( ) ;
60 numberSpinner . f i l l I n T h e I n p u t ( 4 ) ;
61
62 C e l l <CheckboxComponent> c e l l 2 =
row . g e t C e l l ( t a b l e . getColumn4 ( ) ) ;
63 CheckboxComponent checkbox =
c e l l 2 . getContent ( ) . get (0) . getValue ( ) ;
64 checkbox . check ( ) ;
65
66 submitButton . c l i c k ( ) ;
67

68 a s s e r t F a l s e ( v a l i d a t i o n . isThereAnyErrorMessage ( ) ,
69 " There s h o u l d be no e r r o r me ssa ges ! " ) ;
70
71 a s s e r t T r u e ( proceedButton . i s D i s p l a y e d ( ) ,
72 " Proceed button s h o u l d be v i s i b l e i n t h i s moment ! " ) ;
73 }

Listing J.1: Functional test with use of Component Model

82
K Contents of Attached CD
The attached CD contains following directories and files:

• component-model - the sources of created high-level API;

• component-model-showcase - the sources of showcase usage


of the created high-level API;

• java-doc - generated Java documentation for the API;

• thesis.pdf - a PDF version of the thesis.

83

You might also like