Creation – Day One by Dima

And I said, Let there be code: and there was code.

If The Creator of our blue planet completed his huge job in a week I would suppose he had had a very detailed specification.
Its existence is not reflected in canonical texts but it could not have been otherwise – it is hard to go and do something out of thin air.

Before we started writing code to test Recruiting application we spent awful deal of time by clarifying this task. Results we want to obtain, what exactly, in which order and how – all of these questions were answered and morphed from a jumble of ideas, a prebiotic soup, so to say, into a quite articulate system. Remaining was ‘next to nothing’ – come back to earth and write it down.

Let’s start with some basic things – functionality which will be used by higher level classes.

Figure 1

I want to point your attention on how we will use Selenium driver methods. They will be called by each element very often. We also would like to know when particular method was called and parameters passed to it (or what was done in a browser, by the other words) as well as what was a result.
Additionally, we must be able to catch an exception thrown by method as otherwise test will fail midcourse. For example, on attempt to execute a click for a nonexistent element on a page.
This is why each driver method, courier of our orders to browser, will be wrapped by something capable to take care and shout us back if something will happen with a courier. Such wrapper is a class CommonActions. To entertain method-couriers and spy them at the same time we will add a cheerleading team of secret agents – logging methods to it.

Figure 2

Other classes, most likely, should have access to CommonActions.
How we want to present a result of our tests? What will be an output format of errors? How to point to actions which triggered errors? We have no answers at this stage and we will log as much as we can trying to outline errors and warnings.

Class Settings is a storage of parameters we may need to change.

Figure 3

Class Constants is also a way to follow good programming practices.

Figure 4

SalesForce objects level is a level of PHPUnit/TestNG tests. To test all Recruiting application we need to run a test for each SalesForce object such as, Position, Candidate, Job Application, Job Application Review and Employment Website.

We started testing Employment Website only as this is most simple object in this application. This post is about Employment Website object only. First SF object and first version of test suite in Java.

To avoid confusion I would like to explain terminology we use. Even though we talk here in OOP terms ‘Object’ is not the first ‘O’ in OOP. For us Object is a Recruiting application entity like Position or Employment Website. You can associate our object with HTML page for simplicity. Element is a part of an Object and can be associated with HTML form element.
If we look at it from OOP side of things – Object is an OOP object and Element is an OOP object. This is quite obvious and we only use word ‘Object’ as SF application entity.

Class WebsiteObject defines xUnit or TestNG test for object EmploymentWebsites. This class links testing code and xUnit/TestNG. It also instantiates its member class GenericObject with parameters appropriate for an object we are going to test (Employment Websites in our case). WebsiteObject initialises driver/browser before tests and frees them after test completion.

Figure 5

Class GenericObject is built to know everything about SF object – Position, Employment Websites etc. Remember – word “Object” in class name is about SF object not Java object.

Class GenericObject runs common object tests. Sequences like New-Save-Edit are amongst them. It also calls CheckAll() for each object element – ‘Price Per Post’, for example.

Common tests are preliminary tests we run before we start testing SF object. We want to make sure that application works as expected with values we call ‘Known Good Values’ or KGV one night. We add than edit what was added than clone what was edited an finally deleted both created records to make sure we can move further deep down with testing all other complex things. This is our understanding of a process at a time of Rev 54 creation.

Figure 6

To be able to do it GenericObject class holds a list GenericElement-s.

Figure 7

GenericElement knows all about element – name, type, field length etc.
From one side, GenericElement and derived from it classes know what attributes define element (this information is stored in their properties – inputLength, isRequired, validValue, intPlaces…). From the other side, class knows how to test those attributes (by methods checkMaxLength, checkRequired, checkDecimalPlacesCount …).

Figure 8

You can see relationship between GenericObject, GenericElement, CheckValue and SalesForce application building blocks (page – object, form field – element) on a picture below.

Figure 9

1. Test Common Sequences – part of the tests responsible for basic behaviours of SF platform and object we test now. Now this functionality is implemented inside CheckTitles method (see Figure 6.). This method executes with object-record basic actions – save, edit, clone. Apart of checking page titles it also tests if all such actions can be completed with known good values (KGV) and we have got a saved record as a result of each such check.
2. Test Elements – part of tests responsible for testing SF object form elements. Things we specified in our tests – name, type, length etc.

Class CheckValue stores one test value. We had to create a separate class because each test value has its own attributes. We need to have some valid values as well as invalid ones to properly test an element. For valid values we need to know how saved values will look like (not always match with entered value). For invalid values we need to know how error message will look like.

Figure 10

Naturally all element types are descendants of GenericElement but each of them will contain specific tests and test values.
Let’s look at genealogical tree for ‘Price Per Post’ element which belongs to ‘Employment Websites’ object as an example.
On top of basic tests of GenericElement, GenericNumber adds own ones – total and fractional part length test, error message #TooBig (max value) test and implements test for maximum field length.
As each element runs all checks inside CheckAll() and because descendant of GenericElement uses own checks – we need to overload method CheckAll().
For example, for GenericNumber (see Figure 10):

int  checkAll (){

GenericNumber not only has additional checks but also some specific test values:

values.add(new checkValue(" 00 00 123", constants.IT_IS_VALID_VALUE,"","123"));
values.add(new checkValue("1.0.0", constants.IT_IS_INVALID_VALUE));

CurrencyElement is almost like GenericNumber but its value will be shown with a ‘$’ sign after record was saved. It also has different error message ‘Invalid currency’.
Class CurrencyElement adds own test values to what was inherited from GenericNumber:

values.add(new checkValue("$$44", constants.IT_IS_INVALID_VALUE, "Invalid currency"));
values.add(new checkValue("477", constants.IT_IS_VALID_VALUE, "", "$477.00"));

Finally I propose to walk through a chain of calls which are part of an error free test run.

Figure 11

Print this post | Home

Comments are closed.