Skip to main content
This revision made November 07, 2012 18:35, by Olivier LeDiouris

Oracle SOA Testing utilities Wiki

This project provides snippets of code to - ideally - test whatever comes with a WSDL. It uses the utilities of the project ConsolidatedTestEnv (part of this workspace you are looking in).

To be able to write JUnit tests more efficiently, we've provided some base classes. Those classes are:

  • unittests.patterns.services.AsynchronousOneWayUnitTest.java
  • unittests.patterns.services.AsynchronousTwoWayUnitTest.java
  • unittests.patterns.services.SynchronousServiceUnitTest.java

They implement the same interface:

  • unittests.patterns.services.ServiceUnitTestInterface.java

This interface contains the following methods:

        public void firstOfAll();
        public String beforeInvoke(String payload);
        public void afterInvoke();
        public void beforeReceive();
        public String afterReceive(String payload);
        public void evaluate(String payload);
        public void onError(Exception ex);
        public XMLElement getResponsePayload();

Those methods have a default behavior, and the classes provided above do not have to be overriden if their standard behavior is good enough.

Standard Behavior

In the project ConsolidatedTestEnv, there is an Ant script that shows how to run tests based on those classes, it is named basic-test.xml. Here is an example of an Ant task implementing a test:

  <target name="unit.test.asynchronous.2.ways">
    <echo>
    =====================================
    Testing ASynchronous Two Ways Service
    =====================================
    outputfile: asynchronous.2.txt
    </echo>
    <junit printsummary="yes" fork="yes" showoutput="yes" failureproperty="asynchronous.2.fail">      
      <classpath refid="classpath"/>
      <formatter type="plain"/>
      <sysproperty key="verbose" value="${verbose}"/>
      <sysproperty key="properties.file.name" value="<font color='blue'>generic-service-test-async-two-way.properties</font>"/>
      <test name="unittests.patterns.services.AsynchronousTwoWayUnitTest" haltonfailure="no" outfile="asynchronous.2"/>
    </junit>    
    <antcall target="in.case.asynchronous.2.fails"/>
  </target>
 
  <target name="in.case.asynchronous.2.fails" if="asynchronous.2.fail">
    <exec dir="." executable="cat">
      <arg line="asynchronous.2.txt"/>
    </exec>
    <fail message="ASynchronous Two Ways Test stopped the process"/>
  </target>
  

Several things to notice:

  • The name of the test, refering to one the classes mentioned above
  • The System property named "properties.file.name" containing the name of the properties file the test will refer to for execution

properties file

The properties file (generic-service-test-async-two-way.properties in the example, this file is part of the project), contains the following data:

  wsdl.url=http://${proxy.name}:${soa.port.number}/soa-infra/services/default/SOACompositeForInstallationTests/asynctwowaybpelprocess_client_ep?WSDL
  service.name=asynctwowaybpelprocess_client_ep
  service.port=ASyncTwoWayBPELProcess_pt
  service.operation=process
  service.ns.uri=http://xmlns.oracle.com/soatesthelper/SOACompositeForInstallationTests/ASyncTwoWayBPELProcess
  service.input.payload.file=generic-async.2.input.xml
  #service.input.payload.as.string=
  service.output.payload.file=generic-async.2.output.xml
  #service.output.payload.as.string=
  client.reply.to.port=1234
  service.response.timeout=10000
  move.on.if.payload.is.invalid=true
  username=oliv
  password=secret      
  decrypt.async.response=true
  

Here is an explanation of the different items it contains:

wsdl.url The fully qualified URL to reach the WSDL of the service to test. Notice the variables ${proxy.name} and ${soa.port.number}, thay are patched with the content of the properties found in master.properties. This master.properties file is not mandatory anymore.
Also notice that you can write here a URL that does not need any patching.
service.name The name of the service to test. Must exist in the WSDL
service.port The name of the port to test. Must exist in the WSDL
service.operation The name of the operation to invoke. Must exist in the WSDL
service.ns.uri The namespace URI of the payload
service.input.payload.file The name of the file containing the input paylod to invoke the service with
service.input.payload.as.string If the above does not exist, then the payload can be passed as a string. This property contains this string
service.output.payload.file In case the service returns a payload (ie non Asynchrounous-one-way), this property contains the name of the file containg the payload to compare the output to.
service.output.payload.as.string If the above does not exist, the payload to compare the output to can be passed a a string using this property
client.reply.to.port For asynchronous-two-ways services, the HTTP Port value used for the reply-to
service.response.timeout In case you want a timeout for the invocation, put it here in milliseconds.
move.on.if.payload.is.invalid Your payload will be validated against the type definition coming with the WSDL. If the payload is invalid, the test will fail unless this property is set to true.
username If this property is set, then Policy Security will be set. A password will need to be provided.
password Same as above.
decrypt.async.response In case of an asynchronous two ways secured service, the response might come back encrypted. Setting this property to true will decrypt it before the afterReceive(), and as a result, before the evaluate().

The table above contains the variables supported by the base classes. If you are extending those classes, there is nothing preventing you from adding your own properties. This file would in fact be the right place to put them.

A note about the variable hierarchy

The file which has its name in "properties.file.name" can use metadata. You have seen that it can be patched with variable found in master.properties. It will also be patched with the values of System.getProperties(), and finally with environment variables from the System level. For example, if you have in master.properties lines like this:

 machine.name=somebox.us.oracle.com
 soa.port.number=8001

Java has been started with

 -Dcommand.line.variable=Dummy          

and a the system level (shell)

 ADE_VIEW_ROOT=/some/place/somewhere

then, in the file mentioned in "properties.file.name", a line like this:

 some.variable=http://${machine.name}:${soa.port.number}${ADE_VIEW_ROOT}/${command.line.variable}

It will be translated into:

 some.variable=http://somebox.us.oracle.com:8001/some/place/somewhere/Dummy

Again, the order of the patches is:

  1. master.properties
  2. system properties
  3. environment variables

A note about SOAPFaultException

In case a SOAPFaultException is raised during invoke (for Synchronous and ASynchronous two ways services), the the SOAP Fault element is retreieved and returned as the expected payload.
This allows to do negative tests (i.e. when a Fault is thrown as expected, like on authentication failure, for example). Warning: In the case of ASynchronous-one-way services, the fault has to be managed using the onError() method, as no returning payload is expected.

A note about secured services

Secured services can be invoked easily. As we said before, you can set Policy Security by just adding the properties username and password in the properties file associated with the test.
One thing to notice though, is the system property named "oracle.security.jps.config". Notice in the service-test-samples.xml Ant script the target named "unit.test.synchronous.secured", which shows the test of a secured synchronous service.

  <target name="unit.test.synchronous.secured">
    <echo>
    ====================================
    Testing Synchronous Service, 
    with Security
    ====================================
    outputfile: synchronous.secured.txt
    </echo>
    <junit printsummary="yes" fork="yes" showoutput="yes" failureproperty="synchronous.secured.fail">      
      <classpath refid="classpath"/>
      <formatter type="plain"/>
      <sysproperty key="verbose" value="${verbose}"/>
      <sysproperty key="properties.file.name" value="generic-service-test-secured-synchronous.properties"/>
      <sysproperty key="oracle.security.jps.config" value="./security/config/jps-config.xml"/>
      <test name="unittests.patterns.services.SynchronousServiceUnitTest" haltonfailure="no" outfile="synchronous.secured"/>
    </junit>    
    <antcall target="in.case.synchronous.secured.fails"/>
  </target>

The file mentioned in this property must of course exist in your testing environment. In case security if required, the existence of this system property will be verified by the test class, and the test will fail if it is not set.

A note about the classpath

That's part of the beauty of Java, if something fails, there is a 50% chance that it's because of the classpath...
In the sample build files you will find in this workspace, the are quite substancial classpathes. They are based on a property named build.home, that is usually one level above the $JDEV_HOME.
There is also a a custom Ant task that will check if all the entries of the classpath exist. You will see for yourself the source of this task, as well as its definition, but here is the way to use it:

    <resolve.classpath verbose="false" 
                       haltonfailure="no" 
                       failureproperty="classpath.fails">
      <path refid="classpath"/>                       
    </resolve.classpath>                       

If an entry is missing, it will be reported.
If the haltonfailure property is set to "yes", the build will stop if an entry is missing.
In the provided samples, this task is part of the "init" target, which is the first one to run.

A note about parallel tasks

There is apparently a need for such things.
Let us take an example:
You have a Composite that will interact with a Human Task. This Composite has TestSuites implemented, and these are the ones you want to run.
The interaction with the HumanTask will be done with the TaskList API, it will poll the Human Task repository to see if the expected task(s) have shown up in the right lists, and simulate a user's behavior.
This will have to be done as the <ant-sca-test> target is running, i.e. in parallel.
We provide a high level mechanism to implement this kind of feature easily. We are using HTTP as the event and notification delivery mechanism.
All you have to do is to implement the process you want to run in parallel (the polling in the example above) using a testing.util.http.Worker interface.
An example of such a task is given in service-test-samples.xml, see the target named "parallel.task".

  <target name="parallel.tasks">
    <echo message="1. Start worker"/>
    <java classpathref="classpath" classname="testing.util.http.SampleMain">
      <arg line="-verbose on"/>
      <arg line="-port 3456"/>
      <arg line="-nbloop 100"/>
    </java>
    <echo message="2. Wait... (Simulate parallel work)"/>
    <!-- The ant-sca-test would go here instead -->
    <java classpathref="classpath" fork="yes" classname="testing.util.http.WasteTime">
      <arg line="-wait 15000"/>
    </java>
    <echo message="3. Kill them all"/>
    <java classpathref="classpath" fork="yes" classname="testing.util.http.Terminator">
      <arg line="-port 3456"/>
      <arg line="-verbose off"/>
    </java>
    <echo message="4. Done"/>
  </target>

What the tests do, by default

Based on the information contained in the file named by the "properties.file.name", the default tests will:

  • Get the EndPoint URL from the WSDL (this test will fail if the service is not found)
  • Check if the service is up and running
  • Validate the input payload against the type definition (found in the WSDL)
  • Check if the service name is valid
  • Check if the port name is valid
  • Invoke the service (possibly with a timeout, when appropriate)
  • Get the response payload (when appropriate)
  • When appropriate (non async-one-way), compare (using XMLDiff) the Body (or Fault) of the returned payload against the one provided in the properties service.output.payload.file or service.output.payload.as.string.
  • the onError method fails, with the exception as a string (toString() method)

If anything else or more should be performed, then the base class of the test has to be overriden, as described in the next section.

Specific behavior

The methods contained in the ServiceUnitTestInterface interface should provide enough flexibility to who want to implement a specific behavior. Overriding those methods should be sufficient. But nothing is preventing anyone from implementing his own test classes if needed.
The methods of the interface are called in the following sequence:

Order Name Default behavior Comment
1 firstOfAll() None

Properties files are read, endPointURL is found, inputPayload is read.

2 beforeInvoke(payload) returns payload, unchanged

Payload is validated, service name, port name are validated, service is invoked as required.

3 afterInvoke() None Except for Asynchronous one way services
4 beforeReceive() None For Asynchronous two ways services only
5 afterReceive(payload) returns payload, unchanged Except for Asynchronous one way services
6 evaluate(returnedPayload) implements the validation on the output payload against the data passed through service.output.payload.file or service.output.payload.as.string. Except for Asynchronous one way services
everywhere onError(exception) fail

If you look at the source of the base classes, you will notice that the properties read from the properties file are available from all the methods you would override or add, as a global protected java.util.Propeties Object named props.
This also mean that you are free to add your own properties in master.properties as well as in the properties file associated with the test.
There is in the same workspace a project named ServiceUnitTestSamples_level2 that contains examples of Unit test classes overriding the base ones, to implement a behavior different than the default one.
Among other things, they show how to patch the skeleton of a default input payload read from a file.

ADFbc Specific Test Classes

Using the above, we have implemented a couple of classes dedicated to the ADFbc services.
In some cases - specially when the job of the ADFbc operation is not a query - some ID might be returned by the service response, which makes it difficult to compare with a static document. Some value(s) will obviously be different, and that would be a problem.
The first idea would be to override the method afterReceive() or the method evaluate() to do the appropriate distinctions, but this implies an extension of the base class, to do everytime something very similar in every cases.
That is why we provide some base classes, extending the above, ready for ADFbc services testing.
They already override the afterReceive() method. They use additional parameters, living in the associated properties file, here is an example:

 xpath.to.patch.output.1=/{http://xmlns.oracle.com/apps/sample/dtsvc/types/}createWorkerResponse//{http://xmlns.oracle.com/apps/sample/dtsvc/}WorkerId
 value.to.patch.output.1=XXX
 xpath.to.patch.output.2=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
 value.to.patch.output.2=YYY

Notice the radical, and the numeric suffix. Those properties go by pair.
Their goal is to give the XPath expression to a text element, and the value to patch it with.
As the point of truth of an XPath expression in the namespace uri, and not the namespace prefix, the expanded syntax has to be used. It is a bit painful, but it is legal and standard.
In short: you must replace the namespace prefix + ":" with the namespace uri between curly braces.
Once patched, the response document can be compared to a static one.
In addition, in case you want to replace a full node (and not only the text element it contains), you can use:

 xpath.to.patch.output.2=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
 node.to.patch.output.2=<ns:NewAge xmlns:ns="http://xmlns.oracle.com/apps/sample/dtsvc/" extra-attr="value">As deep as you like</ns:NewAge>

Notice that in this case, the expanded syntax is not mandatory, as you provide the xmlns attribute if necessary.
But the value of this property MUST be a valid snippet of XML, with all required namespace URIs and possible prefixes.
Note that you can patch attributes as well:

 xpath.to.patch.output.3=//{http://xmlns.oracle.com/apps/sample/dtsvc/types/}result/@{http://www.w3.org/2001/XMLSchema-instance}type
 value.to.patch.output.3=no:prefix:fo:me      

The available test classes (taking those properties in account) for this purpose are:

  • unittests.patterns.adfbc.ADFbcSynchronousServiceUnitTest
  • unittests.patterns.adfbc.ADFbcAsyncTwoWaysUnitTest

They are part of ServiceUnitTest.jpr, and as such part of jarServiceUnitTest.jar.

Services with Attachments

No problem!
A method getAttachmentIterator() has been added to the ServiceUnitTestHelp class.
I need more input from the people interested in managing attachments, in order to know what they want to do and see if there is a possibility to build something generic.
Today, there is a SampleMain7Attachments.java in the package samples.main of ServiceUnitTest.jpr.
xop attachments There is currently a pending ER (#9770497) for the XOP attachments. By default, the xop tags are not visible in the payload (envelope, body, etc). We asked for a property like KEEP_XOP for those elements to remain visible, so we can relate an attachement an its surrounding element and compare it with the right document.
Here is an example of what we mean:
In a returned payload like this

 <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
         xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <env:Header>
   <wsa:Action>http://xmlns.oracle.com/apps/sample/dtsvc//WorkerService/getWorkerResponse</wsa:Action> 
   <wsa:MessageID>urn:uuid:b34e2f50-e2f7-473b-a4b8-d026d8a1aa96</wsa:MessageID> 
   <wsa:RelatesTo>uuid:58abbbba-999e-45ad-9943-98e23a40af36</wsa:RelatesTo>
   </env:Header>
   <env:Body>
   <ns0:getWorkerResponse xmlns:ns0="http://xmlns.oracle.com/apps/sample/dtsvc/types/">
    <ns2:result xmlns:ns2="http://xmlns.oracle.com/apps/sample/dtsvc/types/"
          xmlns:ns1="http://xmlns.oracle.com/apps/sample/dtsvc/"
          xmlns:ns0="http://xmlns.oracle.com/adf/svc/types/"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="ns1:Worker">
      <ns1:WorkerId>111</ns1:WorkerId>
      <ns1:Name>Tiger</ns1:Name>
      <ns1:Age xsi:nil="true"/>
      <ns1:Birthday xsi:nil="true"/>
      <ns1:Description>
      <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
         href="cid:5f945a48c4c74e92b0c8d0c95c4d3651"/>
    </ns1:Description>
    <ns1:Resume>
      <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
         href="cid:ebd45ab2b1b64b1d915c89d7f22dac6d"/>
    </ns1:Resume>
    <ns1:Salary xsi:nil="true"/>
    <ns1:Bonus xsi:nil="true"/>
    <ns1:LastUpdated xsi:nil="true"/>
  </ns2:result>
   </ns0:getWorkerResponse>
   </env:Body>
 </env:Envelope>
 

what is actually returned by the getSOAPBody or getSOAPEnvelope is this

 <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <env:Header>
     <wsa:Action>http://xmlns.oracle.com/apps/sample/dtsvc//WorkerService/getWorkerResponse</wsa:Action>
     <wsa:MessageID>urn:uuid:b34e2f50-e2f7-473b-a4b8-d026d8a1aa96</wsa:MessageID>
     <wsa:RelatesTo>uuid:58abbbba-999e-45ad-9943-98e23a40af36</wsa:RelatesTo>
   </env:Header>
   <env:Body>
     <ns0:getWorkerResponse xmlns:ns0="http://xmlns.oracle.com/apps/sample/dtsvc/types/">
       <ns2:result xmlns:ns2="http://xmlns.oracle.com/apps/sample/dtsvc/types/"
                   xmlns:ns1="http://xmlns.oracle.com/apps/sample/dtsvc/"
                   xmlns:ns0="http://xmlns.oracle.com/adf/svc/types/"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:type="ns1:Worker">
         <ns1:WorkerId>111</ns1:WorkerId>
         <ns1:Name>Tiger</ns1:Name>
         <ns1:Age xsi:nil="true"/>
         <ns1:Birthday xsi:nil="true"/>
         <ns1:Description/>
         <ns1:Resume/>
         <ns1:Salary xsi:nil="true"/>
         <ns1:Bonus xsi:nil="true"/>
         <ns1:LastUpdated xsi:nil="true"/>
       </ns2:result>
     </ns0:getWorkerResponse>
   </env:Body>
 </env:Envelope>

The xop elements are removed on purpose by the JAX-WS stack...
We need to have them to know for example that the attachment with ID ebd45ab2b1b64b1d915c89d7f22dac6d is a Resume. This ID is in the mime-header of the corresponding attachement.

Business Events

Some composite can be triggered by a business event.
A generic abstract class is provided in order to test those artifacts. The base class is living in ServiceUnitTest.jpr, its name is unittests.patterns.event.RaiseEvent.java.
It contains an abstract method named afterRaisingEvent() that must be overriden in the extended class.
The reason for that is that after raising an event, something else might be performed (like checking if the right composite has been started, maybe...).
Attention! In order to use the standalone J2SE Business Event Raising facility provided by those helper classes, a property has to be set at the server level, in the file $MW_HOME/user_projects/domains/<your domain>/setDomainEnv.sh.

 WLS_JDBC_REMOTE_ENABLED="-Dweblogic.jdbc.remoteEnabled=true"

WLS Servers (including SOA server) must be bounced after modifying that one.

This unit testing class uses a slightly different properties file, like this:

 provider.url=t3://fpp-scm14.us.oracle.com:7012
 admin.user=weblogic
 admin.password=weblogic1
 event.name.space=http://schemas.oracle.com/events/edl/EventDefinition
 event.name=EventNumberOne
 #event.payload.file=
 event.payload.as.string=
 # security.username=Oliv
 # security.password=Secret
 #
 # Some room below, for user specific properties
 # ...

The provider.url property can be patched as the other ones already mentioned, using ${proxy.name} and ${soa.port.number}.
In case security is required, just like before, a system property named "oracle.security.jps.config" must be set and represent the path to jps-config.xml. The properties security.username and security.password are used for authentication.
An example of such a class is given in ServiceUnitTest.jpr, it is unittests.patterns.event.RaiseEventSample.java. This very class is used in service-test-samples.xml, in the target unit.test.event. It goes along with the

Running a suite of such tests a build system

There is in the project ServiceUnitTest.jpr a class named unittests.discovery.TestDiscoverer.java, that relies on some properties file to know what test to run, in a given order.
There is also in the same workspace a project named ServiceUnitTestSample.for.CruiseControl, illustrating the point.
To use it, you have to have a file named test.suite.definition.properties, located at the root of the project containing the tests to run (i.e. sibling of the jpr file).
In case you need more than one test suite to live in the same project, you can do it by overriding the suite() method.
Example:

 public class DiscovererSample
   extends TestDiscoverer
 {
   public static TestSuite suite()
   {
     return TestDiscoverer.suite("alternate.test.suite.definition.properties");
   }
 }

The parameter of the suite() method is the path to the properties file. It can be a fully qualified path.
If not parameter is provided to this method, then the file taken in account will be test.suite.definition.properties

test.suite.definition.properties

Here is an example:

 #
 # Test(s) definition(s) file sample
 #
 classes.directory=extended/classes
 delete.generated.class=true
 use.asm=true
 #
 test.name.1=Test One
 test.class.1=unittests.patterns.services.SynchronousServiceUnitTest
 properties.for.test.1=generic-service-test-synchronous.properties
 verbose.1=false
 skip.1=false
 #
 test.name.2=Test Two
 test.description.2=Asynchrnous two ways with security and timeout. Wow!
 test.class.2=unittests.patterns.services.AsynchronousTwoWayUnitTest
 properties.for.test.2=tamil.properties
 verbose.2=false
 jps.config.file.location.2=./security/config/jps-config.xml
 #
 test.name.3=Test Three
 test.class.3=unittests.patterns.adfbc.ADFbcSynchronousServiceUnitTest
 properties.for.test.3=adfbc.generic.with.patch.properties
 verbose.3=false
 #
 transition.to.file.3=transition.input.xml
 transition.from.xpath.3.1=//{http://xmlns.oracle.com/apps/sample/dtsvc/}WorkerId
 transition.to.xpath.3.1=//{urn:for-test}node-one
 #
 transition.from.xpath.3.2=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
 transition.to.xpath.3.2=//{urn:for-test}node-two
 #
 ...

Note: The properties class.directory and delete.generated.class are used if the property use.asm is set to true
This property is deprecated (its default value is false), as a result, the 3 first lines could be ignored (and not used).

If you relate this file to the Ant build-files we talked about before, containing junit tasks, you will see that the test.suite.definition.properties is semantically equivalent.
Three exception though, some properties are generic for all tests:

  • classes.directory This is the name of the directory where the generated test cases will be compiled. This must be a directory accessible for writing.
  • delete.generated.class In case you want to keep the generated classes on the file system after they've been loaded by the ClassLoader, set that one to false; true is its default value.
  • use.asm ASM is a Java byte code engineering library that you can use instead of the regular Java compiler that comes with the JDK 1.6. It generates the corresponding byte code and injects it in the ClassLoader, without having to access the file system. If this property is set to true (its default being false), then the two propeties mentioned above are useless and meaningless.
    If it is set to true, then you need to include in your project the asm jar-files, located for your convenience in ServiceUnitTest, under lib/asm, next to the XMLUnit ones.
test.name.X Name your test (not used for now)
test.description.X Description of your test (not used for now)
test.class.X The name of the TestCase class to run. Semantically identical to the test@name attribute of the junit Ant task
verbose.X If this is not clear, you need to talk to me (or your shrink)
skip.X Allows you not to run a given test case, if set to "true".

Notice that the X in the properties name in the table above is an int, beginning with 1 for the first test, and incremented by one for the subsequent ones.
The test suite will contain all the tests between 1 and the last one of the sequence. The construction of the suite stops when the sequence is interrupted (i.e. last item, or not incremented by one.
A sequence like 1, 2, 3, 4, 5 will build a suite of 5 tests.
A sequence like 1, 2, 4, 5, 6 will build a sequence of 2 tests.
A sequence like 1, 2, 2, 5, 6 will build a sequence of 2 tests.
A sequence like 2, 3, 4, 5 will build nothing.
In addition, you have transitions. This allows you - to some extend - to use the output of a previous test for the input of the next one.
Example:

 transition.to.file.3=transition.input.xml
 transition.from.xpath.3.1=//{http://xmlns.oracle.com/apps/sample/dtsvc/}WorkerId
 transition.to.xpath.3.1=//{urn:for-test}node-one
 #
 transition.from.xpath.3.2=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
 transition.to.xpath.3.2=//{urn:for-test}node-two
 #
 transition.from.literal.3.3=INIT-VALUE
 transition.to.xpath.3.3=//{urn:for-test}node-three

This transition happens between test 3 and test 4.
It will patch the file - on the file system - named transition.input.xml. You need to make sure this file can be written in (i.e not read only...)
It will do two patches in this case, defined by the properties transition.from.xpath.X.Y and transition.to.xpath.X.Y. Notice the expanded form of the XPath expressions.
Important: Those XPath expressions must return one and only one node.
A commodity has been introduced, to address the case where you have to propagate some values accross steps, for example from test1 to test2... You can use system variables instead of XPath expressions, like this:

 transition.to.file.3=transition.input.xml
 transition.from.xpath.3.1=//{http://xmlns.oracle.com/apps/sample/dtsvc/}WorkerId
 transition.to.xpath.3.1=${worker.id}
 #
 ...
 #
 transition.from.xpath.4.1=${worker.id}
 transition.to.xpath.4.1=//{urn:for-test}node-two

The variable "worker.id" is first set, and then used.
Whatever begins with "${" and finishes with "}" is considered as a system variable.
You can also notice the transition.from.literal.3.2=INIT-VALUE. You can use literal values.
There is also a special type of transition that can be run before the first test, as an initialization. This would have the test index set to 0. It would look like this:

 #
 transition.to.file.0=transition.input.xml
 transition.from.literal.0.1=RE-INITIALIZATION
 transition.to.xpath.0.1=//{urn:for-test}node-one
 #

Only literal values are supported for the "from" part, for obvious reasons (System variables could work, but this is not supported - yet).

Caution! If you are intending to use those transitions, you need to make sure the files you manipulate are writable during the execution of your tests! That could mean that those files have been checked out of ADE. If you end up with a message talking about FileNotFoundException and Read-Only File System, then you are probably in this case we are talking about.

Difference compared to previous revision
* delete.generated.class In case you want to keep the generated classes on the file system after they've been loaded by the ClassLoader, set that one to false; true is its default value. * use.asm ASM is a Java byte code engineering library that you can use instead of the regular Java compiler that comes with the JDK 1.6. It generates the corresponding byte code and injects it in the ClassLoader, without having to access the file system. If this property is set to true (its default being false), then the two propeties mentioned above are useless and meaningless.
If it is set to true, then you need to include in your project the asm jar-files, located for your convenience in ServiceUnitTest, under lib/asm, next to the XMLUnit ones. {|- border="1"> |test.name.X |Name your test (not used for now) |-
 
 
Close
loading
Please Confirm
Close