domenica 1 luglio 2012

Fitnesse 1,2,3: the easy way to software testing web services without developing code


Index

  1. Installing Fitnesse and smartricks to test the HTTP status response of a web page (endpoint/web service)
  2. Test the json response

Let's start

1. Installing Fitnesse and smartricks to test the HTTP status response of a web page (endpoint/web service)

This worked on a Mac.


  • Download http://fitnesse.org/
  • in a terminal, run         java -jar fitnesse-standalone.jar -p 8001
  • download smartricks https://github.com/smartrics/RestFixture      and follow the instructions, i.e. "mvn clean package", download the latest slf4j-api
  • create a page in http://localhost:8001/ with the following imports and run the test


!contents -R2 -g -p -f -h







!define TEST_SYSTEM {slim}
!1 Rest Fixture Acceptance Test Suite - SLIM version




!*****> Classpath Settings 
!path /Users/AndreaF/Downloads/RestFixture-master/target/smartrics-RestFixture-3.1-SNAPSHOT.jar
!path /Users/AndreaF/Downloads/RestFixture-master/target/dependencies/*
!path /Users/AndreaF/Downloads/slf4j-1.7.5/slf4j-simple-1.7.5.jar
**!



|Table:smartrics.rest.fitnesse.fixture.RestFixture | http://www.notonthehighstreet.com/pages|
| GET | /about| 200 |

In this way you successfully verify that your page is returning an http status 200 as expected



|Table:smartrics.rest.fitnesse.fixture.RestFixture | http://www.notonthehighstreet.com/pages|
| GET | /about| 200 | Content-Type:text/html; charset=utf-8|

|Table:smartrics.rest.fitnesse.fixture.RestFixture | http://www.notonthehighstreet.com/pages|
| GET | /about| 200 | Content-Type:application/json|



This is a example for successfully verifying the content type (and a failure to show the difference)


2. Test the json response


|Table:smartrics.rest.fitnesse.fixture.RestFixture | http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.map |
| GET | | 200 | Content-Type:application/json|jsonbody.file=="jquery.min.js"|




What follows is a earlier post (some of it is still valid, just the version of the software are outdated)


P.s. RestFixure used to support XPaths for JSON navigation. Now you have to use jsonbody.


So some example would not work if you use a recente smartrics release

Reference

------

There are plenty of sources which talk about Fitnesse: this blog aims to explain step by step how to install Fitnesse and prepare one test case for software testing web services, without writing a single line of code or knowing anything about programming languages. I would like to say "thank you" to the people who teach Fitnesse through their blogs.

The following instructions are valid for working on both Linux or Windows machine.

Legend: I'm using the following model:
instruction (example) [explanation]
which means: I'm listing the instructions, I'm including specific examples inside round brackets and explanations about the step in squared brackets.



Index

  1. installing Fitnesse
  2. write (copy) test cases and see that Fitnesse works
  3. more explanations
  4. a working example


Let's start
Installing Fitnesse
  1. Dowload xampp (for example xampp-win32-1.7.7-VC9-installer) [because you need a server and a db]
  2. Install xampp
  3. Dowload Fitnesse http://fitnesse.org/ [you need fitnesse.jar which is you starting point, your container of all the test cases and results]
  4. Open a cmd shell  in windows or a shell in linux and C:\...\Downloads\FitnesseDirectory> java -jar fitnesse.jar -p 8080 [install & load Fitnesse]
  5. Go to http://localhost:8080/ [Fitnesse starting page]
Write (copy) test cases and see that Fitnesse works
  1. Here https://github.com/smartrics/RestFixture we can download a zip file (like smartrics-RestFixture-2.0.beta.2-66-gfb35bc29 (click on the "zip" button at the top of the page) [What is it? It is the source code of the java code you need to use to query a web service] [Fitnesse performs the tests according to the java code contained in a .jar file, called fixture]
  2. We unzip the zip file
  3. We build the source code ( here https://github.com/smartrics/RestFixture we find all the instructions: if we prefer to go ahead hassle free, consider to run ant full -Dskip.metric.jdepend=true)
  4. We go to http://localhost:8080/
  5. We click edit and type <page where you are>.<page name for a test suite> and save (for example FrontPage.SandBoxPickUpAnExample) [i.e. you create a new page where you are going to either write test cases or, since it is a test suite, gather more test cases pages together]
  6. We click on the link you have created, then edit [now you are able to write some test cases and perform some tests....almost] [ you can perform the last two operation in reverse order by "adding a child" to the current page and then click edit and modify the current page by adding <page where you are>.<page name for a test suite> ]
  7. We add to the Fitnesse page you are editing, which is still blank [we need to include the header in order to execute the test cases] [ This header is retrieved by C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\fitnesse\FitNesseRoot\RestFixtureTests\SlimTests\Content.txt Without this header the following test would not work]
!define TEST_SYSTEM {slim}
!1 Rest Fixture Acceptance Test Suite - SLIM version


  • add to the Fitnesse page you are editing !path <path>\<name of the fixture>.jar [in order to reference the (java) code which is performing the tests you need to include all the following path] [ we need to reference both RestFixture.jar and the libraries in the lib folder the fixture depends on]

!*****> Classpath Settings 
!path C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2/build/fitnesse/FitNesseRoot/RestFixtureTests/lib 
!path C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2/build/fitnesse/FitNesseRoot/RestFixtureTests/lib/* 
!path C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2/build/fitnesse/FitNesseRoot/RestFixtureTests/lib/log4j.xml 
!path C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\RestFixture.jar 
!path C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\RestFixture_fitnesse.jar 
**!


  • you need of course to substitute the path " C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2/ " with your own [ we want to exploit ready-to-be-used fixtures to test web services, in this case  http://cloud.github.com/downloads/smartrics/RestFixture/RestFixture-2.0.html ; in this way we are referencing "the engine" which Fitnesse will use to execute the tests and all we have to do is to write the test case which queries our web server. Fitnesse will  execute the test and compare the actual response with the one we expect and have specified]  
  • add [ we need also to define some variables which are used by the following examples] [ Retrieved from C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\fitnesse\FitNesseRoot\RestFixtureTests\content.txt ]
 

    !1 Rest Fixture Acceptance Test Suite
    !contents -R2 -g
    !*****> Variables Settings
    !define jettyHost {localhost}
    !define jettyPort {8765}
    !define tempDirectory {./build}
    **!


  • add [ we want to add the setup script table in order to set up the web server which the tests are querying ] [Retrieved from C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\fitnesse\FitNesseRoot\RestFixtureTests\SlimTests\SuiteSetUp ] 

| script |!-smartrics.rest.test.fitnesse.fixture.HttpServerFixture-!|
| check | is started | false |
| start server | ${jettyPort} |
| check | is started | true |



  • add [ Retrieved from C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2/build/fitnesse/FitNesseRoot/RestFixtureTests/SlimTests/SetUp ] 
| script |!-smartrics.rest.test.fitnesse.fixture.HttpServerFixture-!|
| check | is started | true |
| reset resources database |



  • copy some already prepared test cases [ Retrieved from C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\build\fitnesse\FitNesseRoot\RestFixtureTests\SlimTests\GetTests\content.txt]
!3 GET
!**** NotesA GET request is performed on the resource whose URI is specified in the second cell.The following cell indicate:1) the expected return HTTP code,2) a subset of headers - regular expressions are allowed3) a list of XPaths to be executed in the body. Each XPath is run and it suceedes only if the result of the executionreturns at least one node****! 

| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |http://${jettyHost}:${jettyPort}||GET    | /resources/0 | 200 | Content-Length : [\d]+ |!-/resource/name[text()='a funky name'] <br/>/resource/data[text()='an important message']-!| 

!**** Absolute resource pathsA GET (as all other verbs) accepts absolute resource paths.  ****! 

| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |http://${jettyHost}:${jettyPort}||GET    | http://${jettyHost}:${jettyPort}/resources/0 | 200 | Content-Length : [\d]+ |!-/resource/name[text()='a funky name'] <br/>/resource/data[text()='an important message']-!| 

A GET request properly handles query strings. In this example the stub resource echoes the query string in a Query-String header 

| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |http://${jettyHost}:${jettyPort}||GET    | /resources/0?param=echome | 200 | !-Content-Length : [\d]+Query-String : param=echome -! |!-/resource/name[text()='a funky name'] <br/>/resource/data[text()='an important message']-!|



  • save and click test [so we are executing the test cases in the table and getting the results] 


The smartrics fixture does works!

The green shadow we see is a good sign! It means that the java code of the fixture is correctly referenced, so it does perform the test. (If a yellow shadow appears the reason could be that we are running tests against an endpoint of a web service (localhost:8765) which doesn't exist.) 

The point is: we are able to query the web services you have coded/implemented and to perform some tests to verify their functioning. Whether we have coded the fixture code or we have got it ready from other source, the advantage of using Fitnesse is: we can rely on some code communicating with your web service and write hundreds of test cases to verify if the web service answers correctly whichever data you are sending (an example to clarify: once you have a web service performing math division operation and you have some java code able to exchange data with the web service, you can write test cases to verify the functioning by sending a division by zero, a division by a number greater than the maximum supported, ...)

More details and explanations

I suggest to reference the buildfolder because for reasons I don't know some jar libraries are not included in the distribution zip file RestFixture-2.0.beta.3.zip (like log4j.jar, for example).
To have more details, explanations and examples have a look at http://cloud.github.com/downloads/smartrics/RestFixture/RestFixture-2.0.html


A working example

This is a test case where we want to perform a GET request in order to query a WS and retrieve the information related to an organization 322 present in a db. Since the WS requires authentication, we need to set the header of the GET operation, specifically to pass the cookie value (the authentication is based on a cookie). Thanks to the cookie we get access to the information which are retrieved through a json communication
In order to get the value of the cookie so we can set the header of the GET request appropiately, we need to manually login into the web service and retrieve the value of the authentication cookie by having a look to the GET and POST requests through firebug.
setHeader is a method able to modify the GET request before it takes place and https://<web server address> together with /organizations/322 is the url which appears in the browser when we select a specific organization among the ones available in the db and shown by the WS on request


| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |https://fis.absolutesw.com|
| setHeader | Cookie: sessionid=245cafd3020628359200573c2ff14610 |
|GET    | /organizations/322 | 200 |Content-Type : application/json |!- //uri -!|


Anyway in order to retrieve an authentication cookie automatically, the fixture allows to perform the let method.
You can learn about let in the file C:\Users\andrea.ferraresi\Downloads\smartrics-RestFixture-fb35bc2\src\main\java\smartrics\rest\fitnesse\fixture\RestFixture.java
Anyway there should be a small error, since String loc = row.getCell(2).text(); means that we need to specify in the second column after the LET method the location of the value we want to retrieve: in this case we want to retrieve the authentication cookie value so we specify it to be retrieved inside the header of the HTTP response and, contrary to the comment in the RestFixture.java file, we specify the location in the 3rd column
The regex Set-Cookie:sessionid=[0-9a-z]* is able to retrieve the cookie value. [The regular expressions are used to specify a precise element in the header, an xpath expression is used to specify a precise element in the body.]
Set-Cookie: is a regex to extract the value of the http response field Set-Cookie, then we need to specify the string sessionid=[0-9a-z]* because the field Set-Cookie contains more than one value. If we wanted to retrieve a value from the body of the response (we would have written | let | mycookie | body | ...)
This line
setHeader Content-Type : application/x-www-form-urlencoded;charset=UTF-8
is optional



In few details, we set a body for the POST request, we perform the POST request and we get the authentication cookie, we store it in the mycookie variable and use it for the GET operation to retrieve the information about the organization number 322.
Here we have a complete example of a perform a test on the actual body retrieved: the HTTP response is written in json, anyway the fixture we are using is not able to understand json: at the moment what we can do is to write xpath expressions as expected results (like //uri or //name[text()='Incorporation']) and the fixture is able to parse the body of the HTTP response and assert if the actual result is equal to the expected one.
The implicit assertion is that the expected result should be contained in the actual result, which in the example is much longer than the expected one



| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |https://<web server address> |
|setHeader|Content-Type : application/x-www-form-urlencoded;charset=UTF-8|
|setBody|!-email=<username>%40<domain>.com&password=<write here the password>-!|
|POST   | /me?authentication | 201 | | no-body |
| let | mycookie |  header |  sessionid=[0-9a-z]* | sessionid= |



| !-Table:smartrics.rest.fitnesse.fixture.RestFixture-! |https://<web server address> |
| setHeader | Cookie: %mycookie% |
|GET    | /organizations/322 | 200 |Content-Type : application/json |!- //name[text()='Incorporation'] -!|


That's all for this brief "how to" guide to Fitnesse.
If you think you have studied enough for today, you can have a rest by tasting a home-made cocktail prepared by a one of the cocktail masterclass professionals in one of their cocktail evenings in and around London: have a look at the cocktail bar hire http://www.barz8events.co.uk/




This blog is sponsored by Italian Aurora e da Veni Vidi Vici Bici! da 0 a 139 anni. Puoi guardare il video della presentazione di Veni Vidi Vici Bici! da 0 a 139 anni

1 commento: