SiKing

January 29, 2014

defining test categories in SoapUI

Filed under: automation — SiKing @ 1:05 pm
Tags: ,

Categories are a feature of most modern test automation frameworks, which allows you to assign an arbitrary tag to any test, and then subsequently select a group of tests to run only by that tag. JUnit introduced this feature in version 4.8, both TestNG and NUnit have had it for a while. In SoapUI you have to do some tricky naming of your test case and suites in order to be able to achieve this. Or … you could use a custom event.

You want to check for the categories before every test run, so the event has to be a TestRunListener.beforeRun event. Leave the target blank (any test case), and name it anything you like – I used “categories”.

The category tags will be specified in three places: each test is going to be tagged with a category in a property called “categories”. Then at the project level, we want to specify properties “includeCategories” and “excludeCategories”, which will list categories to include and categories to exclude, respectively. Each of these will be just a comma-separated list. First part of our event script is to read all that stuff in:

def testCategories = []
def excludeCategories = []
def includeCategories = []

def tstCats = testRunner.testCase.getPropertyValue("categories")
def exCats = testRunner.testCase.testSuite.project.getPropertyValue("excludeCategories")
def inCats = testRunner.testCase.testSuite.project.getPropertyValue("includeCategories")

if(tstCats != null) tstCats.split(',').each { testCategories << it.trim() }
if(exCats != null) exCats.split(',').each { excludeCategories << it.trim() }
if(inCats != null) inCats.split(',').each { includeCategories << it.trim() }

The first three lines each define an empty List. Next three lines read all the properties in, and the last three lines parse them. We do not want to bother the user with defining a proper List of Strings, such as ["category1", "category2", "etc."], the above code expects that the categories property just specifies something like: category1, category2, etc., no quotes, no brackets.

First let’s deal with exclude categories. The meaning of these is usually that if a test is tagged with any of these, do not run it.

// exclude categories
excludeCategories.each {
	if(testCategories.contains(it))
		testRunner.cancel("${context.testCase.name} TestCase cancelled; excludeCategory = ${it}!")
}

And now the include categories. The meaning of these is that if the test is not tagged, skip it. Only if a test is tagged with any of these, then run it.

// include categories
if(includeCategories.size() != 0) {
	def cancelTest = true
	includeCategories.each {
		if(testCategories.contains(it))
			cancelTest = false
	}

	if(cancelTest)
		testRunner.cancel("${context.testCase.name} TestCase cancelled; includeCategories = ${includeCategories}!")
}

That is it!

As an added bonus, I can also have some automatic category handling, such as:

// Do not bother running LONG tests during work hours.
if(testCategories.contains("LONG")) {
	def rightNow = new GregorianCalendar()
	if(rightNow.get(Calendar.HOUR_OF_DAY) < 17)
		testRunner.cancel("${context.testCase.name} test too long to bother during the day!")
}

Enjoy! 😀

November 1, 2013

testing concurrency with SoapUI

Filed under: automation — SiKing @ 11:02 am
Tags: ,

Testing concurrency in SoapUI is easy, if you know how – just like everything else in life. 🙂 There are several approaches that you can take.

First, let’s define what “concurrency” is. Concurrency, also called a “race condition”, is when multiple requests arrive at the server at the same time, but they each need to be handled separately. A simple example: let’s say that you have $100 in your bank account and you send several requests to withdraw all the money – obviously only one of the requests should succeed and the others should fail due to insufficient funds. If more than one of these requests succeeds, you found a race condition. The cause of concurrency is often improper database locking.

SoapUI has the ability to send requests in parallel at the project level (parallel test suites) or at the test suite level (parallel test cases). I will discuss several possible approaches based on different situations.

Note that in the below discussion in each case we are talking about only one test! However, when I use the terms “test case” and “test suite” I am talking about the level of hierarchy in a SoapUI project.

Case 1: the straightforward suite

In the simplest case you have a situation where only one of multiple requests should succeed, such as the case of withdrawing all the money from one bank account. This case assumes there is no setup or cleanup of any kind.

Start with creating a new test suite in SoapUI and setting the run mode to parallel. testcase parallel mode

Next create the first test case to make one transfer. Do not add any assertions that verify success / failure of the transfer itself – you are expecting only one to succeed and you do not know which one that is going to be. Since timing is important in a concurrency test, keep this lean. Normally I have just a single SOAP Response assertion, or a Valid HTTP Status Codes assertion (if dealing with a REST request).

Clone the test case (using F9) multiple times. As will be seen later, it is a good idea to keep the names of the test cases simple; something like: tranfer0, transfer1, transfer2, etc.

Lastly, you need to handle the verification in the test suite TearDown Script. The exact script will depend on what response you are going to get and what you are looking for. Let’s say that a failed transfer will respond with a SOAP fault, then your verification script could look like the following.

import com.eviware.soapui.support.XmlHolder
def goodTransfer = 0
testSuite.testCases.each {
	def response = new XmlHolder(it.getTestStepByName("transfer").getProperty("Response").value)
	if(response.getDomNode("//*:Fault") == null)
		goodTransfer++
}
assert goodTransfer == 1 : "Too many transfers!"

You will have to adjust the script for your particular situation, but the idea is simple. Read the response of each of the steps (within the test cases in the SoapUI hierarchy) and count the number of successes – there had better be only one.

Case 2: login first

What if you first need to login or generate some other setup?

The only difference from case 1 is the setup – the login. Start with creating everything from case 1.

Next add a test case for the login. It does not matter where in the order of tests you place it (everything runs in parallel anyway), but it helps visually if you place it first. Make sure this test runs correctly and transfers any credentials you may need to your other steps.

Next comes the secret sauce. Disable this test case; this test must be run from the test suite Setup Script with:

testSuite.getTestCaseByName("login").run((com.eviware.soapui.support.types.StringToObjectMap)context, false)

The login could get more complicated if your application requires that HTTP session be maintained. The exact solution to your specific situation is left as an exercise for the reader. 🙂

Case 3a: verify afterwards (at project level)

What if, similarly to case 2, you need to run some sort of cleanup after everything has run. For example: deposit money back so that next run of the same test will work again.

You could take the same approach as in case 2: create a test case at the end of your test suite, disable it, and run it from the suite TearDown Script. However, any tests that are run this way will not get considered when determining if the suite failed or not (the final exit status of the test runner) and will not have any logs created!

In order to work around this, you could set up your entire test as a new SoapUI project. In the project, you will have three test suites: setup, transfers, and cleanup. All test suites are run sequentially, nothing gets disabled, nothing gets run from Setup or TearDown. The setup portion will have only one test case similar to the login from case 2. The transfers portion will have multiple test cases such as all the transfers from case 1 (possibly minus the verification), all run in parallel. The cleanup portion will have one test case like the deposit and any cleanup (and possibly the verification).

Practical example of this situation is that instead of withdrawing all the money from your account, you send in multiple deposits and withdrawals for smaller amounts, and then afterwards the transaction history (a separate API request?) has to show the correct running balance.

The exact implementation of all of this should be pretty straightforward if you got through all the discussion so far.

However, if you are running in a continuous integration system, it is undesirable to have a separate SoapUI project for every concurrency test.

Case 3b: verify afterwards (at test suite level)

You can have a test case wait until other test cases have completed. The magic sauce here is the SoapUI monitor.

Start by creating everything you have done in case 2.

Now create your verification test case. Just as before, it does not matter where in the test suite you place it (everything runs in parallel), but visually it makes more sense to place it at the end. This test does not get disabled, since this is where the verification will take place – you need this test to be considered in the final runner exist status and you want all the logs generated from this step.

In the test suite Setup Script initialize the monitor.

def monitor = new com.eviware.soapui.monitor.TestMonitor()
testSuite.testCases.each {
	testCase = it.value
	if(testCase.label.contains("transfer")) {
		log.info("monitoring: ${testCase.label}")
		monitor.monitorTestCase(testCase)
	}
}
runner.runContext.testMonitor = monitor

If you are less careful about how you name your test cases, the if statement above may become slightly more complicated?

	if(testCase.label.contains("withdrawal") || testCase.label.contains("deposit"))

In the last test case, the verification one, create a new Groovy Script step which will wait for everything else to complete. This step has to be first!

def monitor = context["#TestSuiteRunner#"].runContext.testMonitor
if (monitor == null) {
	log.warn("monitor not found in completion check")
} else {
	while(monitor.hasRunningTests()) {
		log.info("waiting for tests to complete ...")
		try {
			Thread.sleep(100)
		} catch(InterruptedException ignored) { }
	}
	log.info("Tests completed: ${!monitor.hasRunningTests()}")
}

July 25, 2013

SoapUI Cookie management

Filed under: automation — SiKing @ 12:09 pm
Tags: ,

It seems that HTTP session Cookie management in SoapUI is little understood. 😦 Performing several Google searches, supplemented by some emails to SmartBear support, yielded only a lot of confusion. Until one day I happened upon this gem by user “Unibet Support”!

Cookies are normally handled by the client in a “Cookie Store”; in SoapUI they cannot be read/set same as other parameters. I am intentionally using the upper-case C here, as one of my first attempts was: messageExchange.requestHeaders['cookie']. Through some trial and error I discovered that I could use an event like submit.request.requestHeaders['Cookie'] (with the upper-case C), however this was still not the correct path to enlightenment.

You first need to get into the Cookie jar.

import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport
def myCookieStore = HttpClientSupport.getHttpClient().getCookieStore()

Reading Cookies

def myCookies = myCookieStore.getCookies()

This will give you a List. An individual Cookie is going to look something like:

[version: 0][name: JSESSIONID][value: 6ed79202575ff0c178efa2d4d9f1][domain: abcd-zq11][path: /css][expiry: null]

You can access each of the items with a get method, which Groovy usually exposes as a parameter.

assert myCookies[0].getValue() == myCookies[0].value

To get one specific Cookie, you could do something like:

def interestingCookie
myCookies.each {
	if(it.name == "JSESSIONID")
		interestingCookie = it
}

Updating Cookies

To update a Cookie is just as easy. Each of the get methods has a corresponding set method, again in Groovy exposed as a parameter.

interestingCookie.value = "new_cookie_value"

This, of course, updates the Cookie right in the Cookie Store! To avoid this:

def clonedCookie = interestingCookie.clone()
clonedCookie.value = "cookie_not_in_store"

Deleting Cookies

myCookieStore.clear()

will clear out all Cookies from the Store. To delete only one specific Cookie, you could do something like:

interestingCookie.expiryDate = new Date() - 1	// yesterday
myCookieStore.clearExpired(new Date() - 1)

Creating Cookies

This is a little more involved.

import org.apache.http.impl.cookie.BasicClientCookie
def myNewCookie = new BasicClientCookie("cookie_name", "cookie_value")
myNewCookie.version = 1
myNewCookie.domain = "qa.test"
myCookieStore.addCookie(myNewCookie)

Of course you could have done something like:

def myNewCookie = new BasicClientCookie("cookie_name", interestingCookie.value)

July 5, 2013

dynamically create elements in a SoapUI request, JSON version

Filed under: automation — SiKing @ 10:50 am
Tags: ,

One of my previous posts “dynamically create elements in a SoapUI request” seems to be quite popular – 3rd most popular by the number of hits. Well recently I had to achieve the same feat, but this time in JSON for a REST call. So I thought I’d share.

With the release of version 1.8 Groovy introduced native support for JSON.

the challenge

Transform this response of one step:

{
  "leagueId": 22,
  "name": "Bruins at Sabres",
  "rotation": 1401,
  "eventId": 66069,
  "status": "ACTIVE",
  "leagueName": "NHL",
  "startTime": "2013-08-17T09:05:00.000-07:00",
  "home": {
    "selectionId": 1243,
    "name": "Sabres",
    "shortName": "SAB",
    "marketId": 0
  },
  "away": {
    "selectionId": 454,
    "name": "Bruins",
    "shortName": "BRU",
    "marketId": 0
  },
  "markets": [
    {
      "marketId": 428465,
      "name": "Money Line",
      "period": 11,
      "type": {
        "marketTypeId": 2,
        "basicType": "ML"
      },
      "selections": [
        {
          "selectionId": 454,
          "name": "Bruins",
          "shortName": "BRU",
          "position": "A",
          "priceId": 3560954,
          "price": 1.74074074,
          "usprice": "-135",
          "marketId": 428465
        }
      ]
    }
  ]
}

To make it look like this request of the next step:

{
  "bets": [
    {
      "stake": "10.201259570695608",
      "selections": [
        {
          "marketId": 428465,
          "position": "A",
          "price": 1.74074074,
          "selectionId": 454,
          "name": "Bruins",
          "priceId": 3560954,
          "shortName": "BRU",
          "usprice": "-135",
          "event": {
            "startTime": "2013-08-17T09:05:00.000-07:00",
            "leagueId": 22,
            "leagueName": "NHL",
            "eventId": 66069,
            "status": "ACTIVE",
            "rotation": 1401,
            "name": "Bruins at Sabres"
          }
        }
      ]
    }
  ]
}

the solution

The script ended up being surprisingly simple:

import groovy.json.*
def extractSelectionJson(String from) {

	def slurper = new JsonSlurper()
	def result = slurper.parseText(context.expand('${'+ from +'#Response}'))

	def selectionMap = [:]
	result.markets[0].selections[0].each {
		selectionMap[it.key] = it.value
	}

	def eventMap = [:]
	result.each {
		if(it.key.equals("away") || it.key.equals("home") || it.key.equals("markets"))
			return
		eventMap[it.key] = it.value
	}

	selectionMap["event"] = eventMap

	def builder = new JsonBuilder(selectionMap)
	testRunner.testCase.setPropertyValue("selection", JsonOutput.prettyPrint(builder.toString()))
}

Let’s have a look at what is going on.

Everything lives in the groovy.json.* namespace. The JsonSlurper reads and parses JSON using the .parseText() method which takes a string as an input. I will read all of my response into the variable result. I can now access any element in my response as an attribute of result.

Inside my script I will manipulate everything as a map.

In my request, the selections element is at a higher level of hierarchy than in the response. I will read that first (using result.markets[0].selections[0]) and iterate over all the elements. If you deal a lot with XML and XPath, keep in mind that arrays in XPath are one-based (the first one is numbered 1), however Groovy (and Java) arrays are always zero-based (first one is numbered 0); in this case we are manipulating everything in pure Groovy.

Next I build up the “event” map, where all the elements come from a higher level of the hierarchy than where they go into my request. Again, read all the elements and iterate over them (result.each), but this time I want to skip some in the if block.

Repackage everything back together in selectionMap["event"] = eventMap, and rebuild / convert it all back into JSON JsonBuilder(selectionMap).

Lastly there is no way to write this out directly into my test step request, similar to what I have been able to do with SOAP requests. So I write everything out to a SoapUI property, called selection.

If you are paying attention, I never addressed the bets and stake elements. That is because in my particular case I wanted to be able to manipulate the stakes on per test basis. My request now looks like:

{
  "bets": [{
      "stake": "${=Math.random() + 10}",
      "selections": [${#TestCase#selection}]
    }]
}

One more side note. When building all this up I ran into an issue. If any of the strings in my response above contained "\\" (double slash), the JsonSlurper crashed. This is a bug in Groovy, discussed here, and allegedly fixed in Groovy 1.8.4; SoapUI ships with Groovy 1.8.0. There are two possibilities how to work around this in SoapUI.

  1. When you read in the response, you have to read it in as slurper.parseText(context.expand('${'+ from +'#Response}').replaceAll("\\\\", "")). This obliterates all the double slashes, which in some cases may be undesirable.
  2. Install latest Groovy – I used Groovy 2.1.1. Copy the file $GROOVY_HOME/embeddable/groovy-all-*.jar to $SOAPUI_HOME/lib, and remove $SOAPUI_HOME/lib/groovy-all-1.8.0.jar. This could cause problems if you are running your tests on a CI machine that you do not have direct control over.

July 25, 2012

SoapUI external XML DataSource

Filed under: automation — SiKing @ 2:57 pm
Tags: ,

I am normally not a fan of DDT, I tend to lean more towards BDT, so it was only very recently that I started looking at the DataSource test step in SoapUI. The available documentation has a lot of room for improvement. Here is how I was able to use an external XML file(s) as a data source for my test.

I was given three files that have filenames like Visa_AVS.xml and they contain data in the form:

<test accountNumber="4112344112344113" amount="1.00" street="1 Main Street" city="Boston" zip="031010001" expectedAvsResp="B" />

Step 1: read in the raw files

This is done with the DataSource step.

The only thing that I could find to read in a file (other than Excel) is the DataSource = Directory.

I am using SoapUI-Pro and my entire project is a Composite Project, so every TestSuite is a separate directory. I am going to keep all my data sources in the same directory as the TestSuite, so as to make it easier for uploading to SVN. Directory = ${projectDir}/AA-PPS-soapui-project/experimental-Test-Responses-TestSuite

The Filename Filter = *_AVS.xml should be pretty explanatory. The only thing worth mentioning is that the filter must start with an asterix – probably a bug in SoapUI.

At this point there is no way to format the data, so the entire contents will be read into only one Property. It does not matter what you call it; I used “allData“.

I know I have three files, so when I hit the play button, I should get three entries in the Data Log.

DataSource - file

Step 2: format the data

This is also done with a DataSource step.

This time we are dealing with DataSource = XML.

Note that the documentation for Source Step says: “could be another DataSource”. Source Step = DataSource – file (from Step 1).

Source Property = allData – the only one you created in Step 1.

You need the XPath that would select each of the data blocks in your source file. Row XPath = //test

Next start creating the Properties. If you prefer to visualize your data as a spreadsheet grid, then the Row XPath would be each of your rows, and the Properties will be each of the columns. I decided to name each Property after the data attributes, but you can name them anything you like. As soon as you create a Property, the form will automatically start inserting new Column XPaths. The form assumes that your source data is formatted something like:

<test>
   <accountNumber>4112344112344113</accountNumber>
   ...
</test>

and so it inserts XPath like accountNumber/text(). In my case this is not correct, so I needed to Edit this to say @accountNumber. One of my source files, instead of the attribute zip, has an attribute zip5. So I had to edit the XPath to “@zip | @zip5“.

Once you hit the play button, you should see correct data in the Data Log. If you did anything wrong there will probably not be an error, you will just not see correct (any?) data in the Data Log.

DataSource - XML

Step 3: your test steps

At this point you can use any number of any test steps you like. Any of the data above can be accessed with Property expansion, for example ${DataSource - XML#accountNumber}, and can be manipulated just as any other data either in Input or in Assertions.

Step 4: iterate over all data

You need to add two DataSourceLoop steps.

The first will iterate over all the data within one file. So the DataSource Step should be whatever you named your Step 2 above. The Target Step should probably be whatever is the first thing in Step 3 above.

The second iterates over all the files. So the DataSource Step should be whatever you named your Step 1 above. The Target Step should be Step 2 above.

Test Case

 

HTH. 😉

March 20, 2012

debugging SoapUI Groovy scripts in Eclipse

Filed under: automation — SiKing @ 4:27 pm
Tags: ,

The very first thing that I must say: I did not quite get it to work, yet! I am hoping that somebody out there will read this and prod me in the right direction to get the last bit to work – please be gentle.

Step 1: ready SoapUI

You need the Pro version to get this to work, because using this technique you can only debug stuff in the Groovy Script Library.
I have two installations of SoapUI: version 4.0.1 that I use just for debugging, and version 4.0.2 SNAPSHOT that I use for all other work. But that might be a little overkill. 😛

  1. Download/install/configure SoapUI Pro. The most important thing is that you need to refactor any script you want to debug into the script library.
  2. Download and unpack the SoapUI source into the same directory as the installation.
  3. Modify the SoapUI Bootstrap Script; depending on which platform you are running this is going to be in $SOAPUI_HOME/bin/soapui-pro.sh or %SOAPUI_HOME%\bin\soapui-pro.bat if you’re a Window$ weenie. The last line of the script reads something like: java $JAVA_OPTS -cp $SOAPUI_CLASSPATH com.eviware.soapui.SoapUIPro "$@". Modify it to say java $JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8666 -cp $SOAPUI_CLASSPATH com.eviware.soapui.SoapUIPro "$@". The details of what this does can be found in this DW article, by Charles Lu.

Step 2: ready Eclipse

Don’t bother with the Eclipse-SoapUI plugin; not only does it not support any of the Pro features, but it is completely useless.

  1. Download/install/configure Eclipse. I personally prefer Eclipse for Testers, with the Java tools and Groovy tools installed.
  2. Create a new Groovy project and import into it your SoapUI project. Make sure you specify that your scripts folder is where your source files are stored.

    specify scripts as your source folder name

  3. You will need to link in the soapui-pro-4.0.1.jar library with the attached sources, as well as everything in the lib directory as a user library.

    create a user library from everything in $SOAPUI_HOME/lib

    add the soapui-pro-4.0.1.jar and the SoapUI user library to the build path

  4. Create a New Debug Configuration. It is going to be a Remote Java Application running on localhost:8666 to match the port specified when launching SoapUI above.

    create a debug configuration

Step 3: debug

  1. Start SoapUI from the modified script. You should see a message something like: Listening for transport dt_socket at address: 8666.
  2. Fire up Eclipse and start the debug configuration. It should connect to the already running SoapUI.
  3. In Eclipse, in one of your scripts set a breakpoint. In SoapUI run the test that contains this script.
  4. My Eclipse Debug session stops in the correct spot, however:

    now what?

Would appreciate any hints how to resolve this. 😥

January 6, 2012

dynamically create elements in a SoapUI request

Filed under: automation — SiKing @ 11:44 am
Tags: ,

I got this problem – took me like 8 hours to solve, so that qualifies it as a problem. In SoapUI I have a call that responds with something like <night ratePlanID="A" stayDate="B" availCodeID="C" regularPrice="D" totalPrice="E" />. There are multiple of these, the number can change depending on the inputs to this call. I need to create the same number of elements for my next call, and change the attributes around a bit to make it look something like: <hot:night ratePlanID="A" resDate="B" quotedPrice="E" />. Luckily Groovy abstracts away the need for counting things, and I naively thought that manipulating the XML would be a breeze too…

version 1.0

The first useful hints that I got were from the SoapUI tips & tricks. After that getting at the individual attributes is done with attributes.getNamedItem(). After that I just brute-forced my way through it.

// create groovyUtils and XmlHolder for response of my "find room" call
def grUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = grUtils.getXmlHolder("find room#Response")

// place for my final result
def entireXmlFragment = new StringBuilder()

// get only the nodes that I am interested in, and iterate over all of them
holder.getDomNodes("//*:hotel/*:roomType/*:guestCount[1]/*:night").each {

	// create a new node one piece of string at a time
	def oneXmlFragment = new StringBuilder()
	oneXmlFragment << "<hot:night ratePlanID='"
	oneXmlFragment << it.attributes.getNamedItem("ratePlanID").getNodeValue()
	oneXmlFragment << "' resDate='"
	oneXmlFragment << it.attributes.getNamedItem("stayDate").getNodeValue()
	oneXmlFragment << "' quotedPrice='"
	oneXmlFragment << it.attributes.getNamedItem("totalPrice").getNodeValue()
	oneXmlFragment << "' />"
	oneXmlFragment << System.getProperty("line.separator")

	// add the new node to my final result
	entireXmlFragment << oneXmlFragment
}

// push the final result into a property
testRunner.testCase.setPropertyValue("entireXmlFragment", entireXmlFragment.toString())

Now in my next call I just insert ${#TestCase#entireXmlFragment} where I want this XML fragment to be placed. Works, but seems kinda neanderthal.

version 2.0

There has to be a way to manipulate my XmlFragments as XML objects, and there has to be a way to push them directly into the next call? The grUtils.getXmlHolder() led me to holder.getDomNodes(), which gives you back a org.w3c.dom.Node.

// create groovyUtils and XmlHolder for response of my "find room" call
def grUtils = new com.eviware.soapui.support.GroovyUtils(context)
def responseHolder = grUtils.getXmlHolder("find room#Response")

// create XmlHolder for request of my "bookHotelRes" call
def requestHolder = grUtils.getXmlHolder("bookHotelRes#Request")
// find the Node that I am interested in
def requestNode = requestHolder.getDomNode("//*:bookHotelResInput/*:room")
// the Document object is used to create new nodes
def requestDoc = requestNode.getOwnerDocument()

// get only the nodes that I am interested in, and iterate over all of them
responseHolder.getDomNodes("//*:hotel/*:roomType/*:guestCount[1]/*:night").each {

	// create a new Element in the Document
	def oneElement = requestDoc.createElementNS(requestNode.getNamespaceURI(), "night")
	// define all the attributes
	oneElement.setAttribute("ratePlanID", it.attributes.getNamedItem("ratePlanID").getNodeValue())
	oneElement.setAttribute("resDate", it.attributes.getNamedItem("stayDate").getNodeValue())
	oneElement.setAttribute("quotedPrice", it.attributes.getNamedItem("totalPrice").getNodeValue())
	// insert the Element
	requestNode.insertBefore(oneElement, requestNode.getFirstChild())
}

// write the Document out to the request
requestHolder.updateProperty(true)

The above will write out the next Element as the first child. Also, and perhaps more importantly, the above will write it out into your request – if you run your test twice in a row, you will end up with both results (old and new) in your request. This is undesirable, but easy to take care of.

// cleanup from a "previous" run
requestHolder.getDomNodes("//*:bookHotelResInput/*:room/*:night").each {
	requestNode.removeChild(it)
}

HTH 🙂

August 22, 2011

Groovy Selenium WebDriver and SoapUI, part 3

Filed under: automation — SiKing @ 4:25 pm
Tags: , ,

So I got my environment set up and I have been busy coding up new Selenium-WebDriver test suite for a few weeks now.

I first wanted to just state that as great of a tool as SoapUI is, their community support just plain sucks! Any time I navigate to their discussion fora, I can actually hear the crickets in the distance. If you need some help, may I recommend the Service Testing using soapUI (needs login) group at LinkedIn.

The next bit of complaint that I have with SoapUI, is how poorly it integrates with Eclipse!

Now back to your regular programming …

the quick and dirty

So the most obvious, and perhaps the easiest way, to get Selenium and SoapUI to cooperate is:

  1. Install SoapUI.
  2. Download Selenium (you need the selenium-server-standalone-2.*.jar) and drop it into your SoapUI installation (into %SOAPUI_HOME%\bin\ext).
  3. Fire up SoapUI; start a new Project; create a new test case; add a new Groovy step; copy-paste the sample code into the step. I made a few modification: drop the package line, drop the class Selenium2Example and void main lines along with the closing brackets, and change the System.out.println to log.info. My final (full) test code is below.
  4. Click Play. You should see Firefox starting up, navigating to Google, and afterwards you should see the SoapUI log entries.
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import org.openqa.selenium.firefox.FirefoxDriver
import org.openqa.selenium.support.ui.ExpectedCondition
import org.openqa.selenium.support.ui.WebDriverWait

        // Create a new instance of the Firefox driver
        // Notice that the remainder of the code relies on the interface, 
        // not the implementation.
        WebDriver driver = new FirefoxDriver()

        // And now use this to visit Google
        driver.get("http://www.google.com")

        // Find the text input element by its name
        WebElement element = driver.findElement(By.name("q"))

        // Enter something to search for
        element.sendKeys("Cheese!")

        // Now submit the form. WebDriver will find the form for us from the element
        element.submit()

        // Check the title of the page
        log.info("Page title is: " + driver.getTitle())
        
        // Google's search is rendered dynamically with JavaScript.
        // Wait for the page to load, timeout after 10 seconds
        (new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
            public Boolean apply(WebDriver d) {
                return d.getTitle().toLowerCase().startsWith("cheese!")
            }
        });

        // Should see: "cheese! - Google Search"
        log.info("Page title is: " + driver.getTitle())
        
        //Close the browser
        driver.quit()

Success, the two can talk to each other. ❗ You will probably notice some errors, due to Google updating their site and the above code no longer works there; however, the proof of concept is there. For a better example, see my sample code.

the difficult way

I did not get as much chance to play with the SoapUI as I would have liked, but I wanted to get this published. The above will work for simple Selenium steps. However, for more complex steps you probably want a little more.

Unfortunately, I have not had a chance to explore this yet, but the general idea is:

  • SoapUI is a java project, it must be in some .jars somewhere, hopefully in just one.
  • Import that into your Groovy (Java) project.
  • Then you should be able to call appropriate functions from your code.

All this sounds quite easy, but I am certain that it will need more than what I have here. If anyone manages to get this to work, I would be really curious to hear from you.

August 8, 2011

Groovy Selenium WebDriver and SoapUI, part 2

Filed under: automation — SiKing @ 2:55 pm
Tags: , ,

I initially assumed that I would have this post up within a week of the previous, but life got in the way as it so often does. 😐

Now that I got everything set up, it’s time to move on. In this second part, I am going to concentrate on getting Selenium 2 WebDriver going with Groovy. Selenium 2 out of the box supports .NET and Java, so why Groovy? There are several reasons: 1. SoapUI (to be discussed later) supports Groovy natively, 2. I like scripted languages for test automation better than compiled languages, and 3. why not?

I had been working with Selenium RC and .NET for some time, and had put together the basis of an automation framework. So my first step was to rewrite everything in Java, and just call it Groovy. All this was actually surprisingly easy to accomplish, especially with my very limited knowledge of both Java and Groovy. I want to stress that what I have here (the previous two links) is just the beginnings of a test framework. It meets my initial requirements: that it run in Groovy, and that it use 100% WebDriver. I am certain that it can (and will) be further optimized, but I would hope that anyone starting with this will get a good idea of where this is heading.

still to do:

  • Get everything running from the command line.
  • Use it in a real-world project. :mrgreen:
  • Make everything more Groovy.

couple of surprises along the way:

  • Man, love the lack of Selenium server. No more Java memory crashes. 👿 Yay!
  • In JUnit4 the signature of asserts changed from (NUnit’s) Assert.AreEqual(expected, actual, message) to Assert.assertEquals(message, expected, actual). The message goes at the beginning?
  • In webDriver, getting the value of a textbox changed from selenium.GetValue("name=q") to txtSearch.getAttribute("value"). Nice!

July 23, 2011

Groovy Selenium WebDriver and SoapUI, part 1

Filed under: automation,linux,windows — SiKing @ 4:13 pm
Tags: , ,

I recently started a new job and a new project that called for me to make use of some things I have used separately over the past few years: combine SoapUI and Selenium into one framework, and make them work together – actually pass information from one to the other and back. While I am at it, I thought I would dust off some skillz from a box that I have not been in for some time: Eclipse and Java (I know the title says Groovy, I’ll get to that).

setting it all up on Windows

Of course at work they must run Windows. 😦

  1. Download and install (unpack?) Eclipse Classic 3.7, and run the Check for Updates. Mental note: gotta look at Eclipse for Testers, someday.
  2. You need to give it Java: set JAVA_HOME and add %JAVA_HOME%\bin to the PATH. The first one that I tried – there were like half-dozen different versions on my machine 🙄 – Eclipse complained that it is missing something called jvm.dll. Better get the real thing.
  3. If you create a shortcut to launch Eclipse from your desktop, I found that it is a good idea to set the “Start in:” field to the same thing as what your workspace is.
    Eclipse shortcut properties
  4. Install SoapUI. This plugin needs some post-install work/commentary. If you also run the SoapUI IDE, especially a different version than what you just downloaded, the two will share one %userProfile%\soapui-settings.xml and there could be collisions; I would really like to find a way to relocate this file for the Eclipse plugin. Also, if you did not start Eclipse from your workspace – point 3 above – then you are going to 1) possibly overwrite your %userProfile%\default-soapui-workspace.xml, and 2) possibly pollute your Eclipse installation with three *.log files that SoapUI always creates on startup. Lastly: what used to be %SOAPUI_HOME%\bin\ext (external jars that should be added to soapUI classpath, for example JDBC drivers) is now %userProfile%\ext; another thing I would really like to relocate for the Eclipse plugin.
  5. Install Groovy. The instructions say to use http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.7/, but if you read between the lines, you will notice this is the development build and as such it changes often, like almost daily. I used http://dist.springsource.org/release/GRECLIPSE/e3.7/ and it seems to have worked right out of the box.
  6. Install SVN. I am not sure why Eclipse still comes pre-installed with CVS; does anyone still use this? When you’re done, make sure it worked. Normally there are problems.

setting it all up on Linux

Of course at home I run Linux. Surprisingly the Linux setup was a little more work. 😕

  1. I run Linux Mint 9 (Ubuntu Lucid Lynx – LTS); the repos have only Eclipse 3.5, which is way too outdated by now. Download and install (unpack?) Eclipse Classic 3.7, and run the Check for Updates.
  2. LM9 comes set up with OpenJDK. Eclipse will run with this, however, when doing this last time, I ran into some problems, like various things kept crashing the JVM. Somewhere on the Eclipse site (unfortunately, I cannot find the link now) they suggested that you use genuine Sun Java. This is accomplished with sudo apt-get install sun-java-jdk, and then you need to modify your eclipse.ini to point to /usr/lib/jvm/java-6-sun/bin/java.
  3. Install SoapUI. I’m still having problems with this one.
  4. Install Groovy. Use the same location as mentioned above, which makes it work right out of the box.
  5. Install SVN. Fix the problems.

Blog at WordPress.com.