Skip to main content

Source code file content

Revision: 114

» Project Revision History

» Checkout URL

soatestingutilities / ConsolidatedTestEnv / readme.html

Size: 41661 bytes, 1 line
<html>
  <head><title>Service Testing</title></head>
  <body>
    <b>
      To see it at work, in the project ServiceUnitTestSamples, run the Ant script named 
      service-test-samples.xml, target "all".
    </b>
    <p>
      This project ServiceUnitTestSamples gathers samples of Service Interface Testing.
      <br>
      It can - ideally - test whatever comes with a WSDL.
      <br>
      It uses the utilities of the project ServiceUnitTest (part of this workspace you are look in).
      <br>
      To be able to write JUnit tests more efficiently, we've provided some base classes.
      Those classes are:
      <ul>
        <li type="disc">unittests.patterns.services.AsynchronousOneWayUnitTest.java</li>
        <li type="disc">unittests.patterns.services.AsynchronousTwoWayUnitTest.java</li>
        <li type="disc">unittests.patterns.services.SynchronousServiceUnitTest.java</li>
      </ul>
      They implement the same interface:
      <ul>
        <li type="disc">unittests.patterns.services.ServiceUnitTestInterface.java</li>
      </ul>
      This interface contains the following methods:
      <pre>
        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();
      </pre>      
      Those methods have a default behavior, and the classes provided above do not have to be 
      overriden if their standard behavior is good enough.
    </p>
    <p>
      <h2>Standard Behavior</h2>
      In the project ServiceUnitTestSamples, there is an Ant script
      that shows how to run tests based on those classes, it is named service-test-samples.xml.
      <br>
      Here is an example of an Ant task implementing a test:
      <pre>
  &lt;target name="unit.test.asynchronous.2.ways">
    &lt;echo>
    =====================================
    Testing ASynchronous Two Ways Service
    =====================================
    outputfile: asynchronous.2.txt
    &lt;/echo>
    &lt;junit printsummary="yes" fork="yes" showoutput="yes" failureproperty="asynchronous.2.fail">      
      &lt;classpath refid="classpath"/>
      &lt;formatter type="plain"/>
      &lt;sysproperty key="verbose" value="${verbose}"/>
      &lt;sysproperty key="<font color='blue'>properties.file.name</font>" value="<font color='blue'>generic-service-test-async-two-way.properties</font>"/>
      &lt;test name="<font color='red'>unittests.patterns.services.AsynchronousTwoWayUnitTest</font>" haltonfailure="no" outfile="asynchronous.2"/>
    &lt;/junit>    
    &lt;antcall target="in.case.asynchronous.2.fails"/>
  &lt;/target>

  &lt;target name="in.case.asynchronous.2.fails" if="asynchronous.2.fail">
    &lt;exec dir="." executable="cat">
      &lt;arg line="asynchronous.2.txt"/>
    &lt;/exec>
    &lt;fail message="ASynchronous Two Ways Test stopped the process"/>
  &lt;/target>
      </pre>
      Several things to notice:
      <ul>
        <li type="disc">The name of the test, refering to one the classes mentioned above</li>
        <li type="disc">The System property named "properties.file.name" containing the name of the properties file the test will refer to for execution</li>
      </ul>
      <h4>properties file</h4>
      The properties file (generic-service-test-async-two-way.properties in the example, this file is part of the project),
      contains the following data:
      <pre>
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=&lt;dummy-stuff/>
service.output.payload.file=generic-async.2.output.xml
#service.output.payload.as.string=&lt;dummy-thing/>
client.reply.to.port=1234
service.response.timeout=10000
move.on.if.payload.is.invalid=true
username=oliv
password=secret      
decrypt.async.response=true
      </pre>
      Here is an explanation of the different items it contains:
      <table border="1">
        <tr>
          <td valign="top">wsdl.url</td>
          <td valign="top">
            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. <b>This master.properties file is not mandatory anymore</b>.
            <br>
            Also notice that you can write here a URL that does not need any patching.             
          </td>
        </tr>
        <tr>
          <td valign="top">service.name</td>
          <td valign="top">The name of the service to test. Must exist in the WSDL</td>
        </tr>
        <tr>
          <td valign="top">service.port</td>
          <td valign="top">The name of the port to test. Must exist in the WSDL</td>
        </tr>
        <tr>
          <td valign="top">service.operation</td>
          <td valign="top">The name of the operation to invoke. Must exist in the WSDL</td>
        </tr>
        <tr>
          <td valign="top">service.ns.uri</td>
          <td valign="top">The namespace URI of the payload</td>
        </tr>
        <tr>
          <td valign="top">service.input.payload.file</td>
          <td valign="top">The name of the file containing the input paylod to invoke the service with</td>
        </tr>
        <tr>
          <td valign="top">service.input.payload.as.string</td>
          <td valign="top">If the above does not exist, then the payload can be passed as a string. This property contains this string</td>
        </tr>
        <tr>
          <td valign="top">service.output.payload.file</td>
          <td valign="top">
            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.
          </td>
        </tr>
        <tr>
          <td valign="top">service.output.payload.as.string</td>
          <td valign="top">If the above does not exist, the payload to compare the output to can be passed a a string using this property</td>
        </tr>
        <tr>
          <td valign="top">client.reply.to.port</td>
          <td valign="top">For asynchronous-two-ways services, the HTTP Port value used for the reply-to</td>
        </tr>
        <tr>
          <td valign="top">service.response.timeout</td>
          <td valign="top">In case you want a timeout for the invocation, put it here in milliseconds.</td>
        </tr>
        <tr>
          <td valign="top">move.on.if.payload.is.invalid</td>
          <td valign="top">
            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.
          </td>
        </tr>
        <tr>
          <td valign="top">username</td>
          <td valign="top">
            If this property is set, then Policy Security will be set.
            A password will need to be provided.
          </td>
        </tr>
        <tr>
          <td valign="top">password</td>
          <td valign="top">Same as above.</td>
        </tr>
        <tr>
          <td valign="top">decrypt.async.response</td>
          <td valign="top">
            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().
          </td>
        </tr>
      </table>
      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.
      <dl>
        <dt><b>A note about the variable hierarchy</b></dt>
        <dd>
          The file which has its name in "properties.file.name" can use metadata.
          <br>
          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.
          <br>
          For example, if you have in master.properties lines like this:
          <pre>
 machine.name=somebox.us.oracle.com
 soa.port.number=8001
          </pre>
          Java has been started with
          <pre>
 -Dcommand.line.variable=Dummy          
          </pre>
          and a the system level (shell)
          <pre>
 ADE_VIEW_ROOT=/some/place/somewhere
          </pre>
          then, in the file mentioned in "properties.file.name", a line like this:
          <pre>
 some.variable=http://${machine.name}:${soa.port.number}${ADE_VIEW_ROOT}/${command.line.variable}          
          </pre>
          It will be translated into:
          <pre>
 some.variable=http://somebox.us.oracle.com:8001/some/place/somewhere/Dummy
          </pre>
          Again, the order of the patches is:
          <ol>
            <li type="1">master.properties</li>
            <li type="1">system properties</li>
            <li type="1">environment variables</li>
          </ol>
        </dd>
      </dl>
      <dl>
        <dt><b>A note about SOAPFaultException</b></dt>
        <dd>
          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.
          <br>
          This allows to do negative tests (i.e. when a Fault is thrown as expected, like on authentication
          failure, for example).
          <br>
          <i>Warning:</i> In the case of ASynchronous-one-way services, the fault has to be managed using the onError() 
          method, as no returning payload is expected.
        </dd>
      </dl>
      <dl>
        <dt><b>A note about secured services</b></dt>
        <dd>
          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.
          <br>
          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.
          <pre>
  &lt;target name="unit.test.synchronous.secured">
    &lt;echo>
    ====================================
    Testing Synchronous Service, 
    with Security
    ====================================
    outputfile: synchronous.secured.txt
    &lt;/echo>
    &lt;junit printsummary="yes" fork="yes" showoutput="yes" failureproperty="synchronous.secured.fail">      
      &lt;classpath refid="classpath"/>
      &lt;formatter type="plain"/>
      &lt;sysproperty key="verbose" value="${verbose}"/>
      &lt;sysproperty key="properties.file.name" value="generic-service-test-secured-synchronous.properties"/>
      <b><font color="red">&lt;sysproperty key="oracle.security.jps.config" value="./security/config/jps-config.xml"/></font></b>
      &lt;test name="unittests.patterns.services.SynchronousServiceUnitTest" haltonfailure="no" outfile="synchronous.secured"/>
    &lt;/junit>    
    &lt;antcall target="in.case.synchronous.secured.fails"/>
  &lt;/target>
          </pre>
          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.
        </dd>
      </dl>
      <dl>
        <dt><b>A note about the classpath</b></dt>
        <dd>
          That's part of the beauty of Java, if something fails, there is a 50% chance that it's
          because of the classpath...
          <br>
          In the sample build files you will find in this workspace, the are quite substancial classpathes.
          They are based on a property named <font face="courier">build.home</font>, that is usually 
          one level above the $JDEV_HOME.
          <br>
          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:
          <pre>
    &lt;resolve.classpath verbose="false" 
                       haltonfailure="no" 
                       failureproperty="classpath.fails">
      &lt;path refid="classpath"/>                       
    &lt;/resolve.classpath>                       
          </pre>
          If an entry is missing, it will be reported.
          <br>
          If the haltonfailure property is set to "yes", the build will stop if an entry is missing.
          <br>
          In the provided samples, this task is part of the "init" target, which is the first one to run.
        </dd>
      </dl>
      <dl>
        <dt><b>A note about parallel tasks</b></dt>
        <dd>
          There is apparently a need for such things.
          <br>
          Let us take an example:
          <br>
          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.
          <br>
          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.
          <br>
          This will have to be done as the &lt;ant-sca-test> target is running, i.e. in parallel.
          <br>
          We provide a high level mechanism to implement this kind of feature easily. We are using
          HTTP as the event and notification delivery mechanism.
          <br>
          All you have to do is to implement the process you want to run in parallel (the polling in the example above)
          using a <font face="courier">testing.util.http.Worker</font> interface.
          <br>
          An example of such a task is given in service-test-samples.xml, see the target named "parallel.task".
          <pre>
  &lt;target name="parallel.tasks">
    &lt;echo message="1. Start worker"/>
    &lt;java classpathref="classpath" classname="testing.util.http.SampleMain">
      &lt;arg line="-verbose on"/>
      &lt;arg line="-port 3456"/>
      &lt;arg line="-nbloop 100"/>
    &lt;/java>
    &lt;echo message="2. Wait... (Simulate parallel work)"/>
    &lt;!-- The ant-sca-test would go here instead -->
    &lt;java classpathref="classpath" fork="yes" classname="testing.util.http.WasteTime">
      &lt;arg line="-wait 15000"/>
    &lt;/java>
    &lt;echo message="3. Kill them all"/>
    &lt;java classpathref="classpath" fork="yes" classname="testing.util.http.Terminator">
      &lt;arg line="-port 3456"/>
      &lt;arg line="-verbose off"/>
    &lt;/java>
    &lt;echo message="4. Done"/>
  &lt;/target>
          </pre>
        </dd>
      </dl>
      <h3>What the tests do, by default</h3>
      Based on the information contained in the file named by the "properties.file.name", the default tests will:
      <ul>
        <li type="disc">Get the EndPoint URL from the WSDL (this test will fail if the service is not found)</li>
        <li type="disc">Check if the service is up and running</li>
        <li type="disc">Validate the input payload against the type definition (found in the WSDL)</li>
        <li type="disc">Check if the service name is valid</li>
        <li type="disc">Check if the port name is valid</li>
        <li type="disc">Invoke the service (possibly with a timeout, when appropriate)</li>
        <li type="disc">Get the response payload (when appropriate)</li>
        <li type="disc">
          When appropriate (non async-one-way), compare (using XMLDiff) the <b>Body</b> (or <b>Fault</b>) of the returned payload
          against the one provided in the properties service.output.payload.file or service.output.payload.as.string.
        </li>
        <li type="disc">the onError method fails, with the exception as a string (toString() method)</li>
      </ul>
      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.
    </p>
    <p>
      <h2>Specific behavior</h2>
      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.
      <br>
      The methods of the interface are called in the following sequence:
      <table border="1">
        <tr>
          <th>Order</th>
          <th>Name</th>
          <th>Default behavior</th>
        </tr>
        <tr>
          <td valign="top">1</td>
          <td valign="top">firstOfAll()</td>
          <td valign="top">None</td>
        </tr>
        <tr>
          <td valign="top" colspan="4">
            Properties files are read, endPointURL is found, inputPayload is read.
          </td>
        </tr>
        <tr>
          <td valign="top">2</td>
          <td valign="top">beforeInvoke(payload)</td>
          <td valign="top">returns payload, unchanged</td>
        </tr>
        <tr>
          <td valign="top" colspan="4">
            Payload is validated, service name, port name are validated, service is invoked as required.
          </td>
        </tr>
        <tr>
          <td valign="top">3</td>
          <td valign="top">afterInvoke()</td>
          <td valign="top">None</td>
          <td valign="top">Except for Asynchronous one way services</td>
        </tr>
        <tr>
          <td valign="top">4</td>
          <td valign="top">beforeReceive()</td>
          <td valign="top">None</td>
          <td valign="top">For Asynchronous two ways services only</td>
        </tr>
        <tr>
          <td valign="top">5</td>
          <td valign="top">afterReceive(payload)</td>
          <td valign="top">returns payload, unchanged</td>
          <td valign="top">Except for Asynchronous one way services</td>
        </tr>
        <tr>
          <td valign="top">6</td>
          <td valign="top">evaluate(returnedPayload)</td>
          <td valign="top">
            implements the validation on the output payload against the data 
            passed through service.output.payload.file or service.output.payload.as.string.
          </td>
          <td valign="top">Except for Asynchronous one way services</td>
        </tr>
        <tr>
          <td valign="top">everywhere</td>
          <td valign="top">onError(exception)</td>
          <td valign="top">
            fail
          </td>
          <td valign="top"></td>
        </tr>
      </table>
      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 <b>props</b>.
      <br>
      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.
      <br>
      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.
      <br>
      Among other things, they show how to patch the skeleton of a default input payload read from a file.
    </p>
    <p>
      <h2>ADFbc Specific Test Classes</h2>
      Using the above, we have implemented a couple of classes dedicated to the ADFbc services.
      <br>
      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.
      <br>
      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.
      <br>
      That is why we provide some base classes, extending the above, ready for ADFbc services testing.
      <br>
      They already override the afterReceive() method. They use additional parameters, living in the associated properties file,
      here is an example:
      <pre>
xpath.to.patch.output.<b>1</b>=/{http://xmlns.oracle.com/apps/sample/dtsvc/types/}createWorkerResponse//{http://xmlns.oracle.com/apps/sample/dtsvc/}WorkerId
value.to.patch.output.<b>1</b>=XXX
xpath.to.patch.output.<b>2</b>=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
value.to.patch.output.<b>2</b>=YYY
      </pre>
      Notice the radical, and the numeric suffix. Those properties go by pair.
      <br>
      Their goal is to give the XPath expression to a text element, and the value to patch it with.
      <br>
      As the point of truth of an XPath expression in the namespace uri, and not the namespace prefix, the <b>expanded syntax</b> has
      to be used. It is a bit painful, but it is legal and standard.
      <br>
      In short: you must replace the namespace prefix + ":" with the namespace uri between curly braces.
      <br>
      Once patched, the response document can be compared to a static one.
      <br>
      In addition, in case you want to <b><u>replace</u></b> a full node (and not only the text element it contains), you can use:
      <pre>
xpath.to.patch.output.<b>2</b>=//{http://xmlns.oracle.com/apps/sample/dtsvc/}Age
<b>node</b>.to.patch.output.<b>2</b>=&lt;ns:NewAge xmlns:ns="http://xmlns.oracle.com/apps/sample/dtsvc/" extra-attr="value">As deep as you like&lt;/ns:NewAge>
      </pre>
      Notice that in this case, the expanded syntax is not mandatory, as you provide the xmlns attribute if necessary.
      <br>
      <i>But the value of this property <b>MUST</b> be a <u>valid</u> snippet of XML, with all required namespace URIs and possible prefixes.</i>
      <br>
      Note that you can patch attributes as well:
      <pre>
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      
      </pre>
      The available test classes (taking those properties in account) for this purpose are:
      <ul>
        <li type="disc"><font face="courier">unittests.patterns.adfbc.ADFbcSynchronousServiceUnitTest</font></li>
        <li type="disc"><font face="courier">unittests.patterns.adfbc.ADFbcAsyncTwoWaysUnitTest</font></li>
      </ul>
      They are part of ServiceUnitTest.jpr, and as such part of jarServiceUnitTest.jar.
    </p>
    <p>
      <h2>Services with Attachments</h2>
      No problem!
      <br>
      A method getAttachmentIterator() has been added to the ServiceUnitTestHelp class.
      <br>
      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.
      <br>
      Today, there is a SampleMain7Attachments.java in the package samples.main of ServiceUnitTest.jpr.
      <br>
      <dl>
        <dt><b>xop attachments</b></dt>
        <dd>
          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.
          <br>
          Here is an example of what we mean:
          <br>
          In a returned payload like this
          <pre>
&lt;env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:wsa="http://www.w3.org/2005/08/addressing">
  &lt;env:Header>
    &lt;wsa:Action>http://xmlns.oracle.com/apps/sample/dtsvc//WorkerService/getWorkerResponse&lt;/wsa:Action>
    &lt;wsa:MessageID>urn:uuid:b34e2f50-e2f7-473b-a4b8-d026d8a1aa96&lt;/wsa:MessageID>
    &lt;wsa:RelatesTo>uuid:58abbbba-999e-45ad-9943-98e23a40af36&lt;/wsa:RelatesTo>
  &lt;/env:Header>
  &lt;env:Body>
    &lt;ns0:getWorkerResponse xmlns:ns0="http://xmlns.oracle.com/apps/sample/dtsvc/types/">
      &lt;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">
        &lt;ns1:WorkerId>111&lt;/ns1:WorkerId>
        &lt;ns1:Name>Tiger&lt;/ns1:Name>
        &lt;ns1:Age xsi:nil="true"/>
        &lt;ns1:Birthday xsi:nil="true"/>
        &lt;ns1:Description>
          <font color="red">&lt;xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
                       href="cid:5f945a48c4c74e92b0c8d0c95c4d3651"/></font>
        &lt;/ns1:Description>
        &lt;ns1:Resume>
          <font color="red">&lt;xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
                       href="cid:ebd45ab2b1b64b1d915c89d7f22dac6d"/></font>
        &lt;/ns1:Resume>
        &lt;ns1:Salary xsi:nil="true"/>
        &lt;ns1:Bonus xsi:nil="true"/>
        &lt;ns1:LastUpdated xsi:nil="true"/>
      &lt;/ns2:result>
    &lt;/ns0:getWorkerResponse>
  &lt;/env:Body>
&lt;/env:Envelope>
          </pre>
          what is actually returned by the getSOAPBody or getSOAPEnvelope is this
          <pre>
&lt;env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:wsa="http://www.w3.org/2005/08/addressing">
  &lt;env:Header>
    &lt;wsa:Action>http://xmlns.oracle.com/apps/sample/dtsvc//WorkerService/getWorkerResponse&lt;/wsa:Action>
    &lt;wsa:MessageID>urn:uuid:b34e2f50-e2f7-473b-a4b8-d026d8a1aa96&lt;/wsa:MessageID>
    &lt;wsa:RelatesTo>uuid:58abbbba-999e-45ad-9943-98e23a40af36&lt;/wsa:RelatesTo>
  &lt;/env:Header>
  &lt;env:Body>
    &lt;ns0:getWorkerResponse xmlns:ns0="http://xmlns.oracle.com/apps/sample/dtsvc/types/">
      &lt;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">
        &lt;ns1:WorkerId>111&lt;/ns1:WorkerId>
        &lt;ns1:Name>Tiger&lt;/ns1:Name>
        &lt;ns1:Age xsi:nil="true"/>
        &lt;ns1:Birthday xsi:nil="true"/>
        <font color="red">&lt;ns1:Description/>
        &lt;ns1:Resume/></font>
        &lt;ns1:Salary xsi:nil="true"/>
        &lt;ns1:Bonus xsi:nil="true"/>
        &lt;ns1:LastUpdated xsi:nil="true"/>
      &lt;/ns2:result>
    &lt;/ns0:getWorkerResponse>
  &lt;/env:Body>
&lt;/env:Envelope>
          </pre>
          The xop elements are removed on purpose by the JAX-WS stack...
          <br>
          We need to have them to know for example that the attachment with ID <font color="red">ebd45ab2b1b64b1d915c89d7f22dac6d</font>
          is a Resume. This ID is in the mime-header of the corresponding attachement.
        </dd>
      </dl>
    </p>
    <p>
      <h2>Business Events</h2>
      Some composite can be triggered by a business event.
      <br>
      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.
      <br>
      It contains an abstract method named afterRaisingEvent() that must be overriden in the extended class.
      <br>
      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...).
      <br>
      <dl>
        <dt><b>Attention!</b></dt>
        <dd>
          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/&lt;your domain>/setDomainEnv.sh.
          <pre>
 WLS_JDBC_REMOTE_ENABLED="-Dweblogic.jdbc.remoteEnabled=true"
          </pre>
          WLS Servers (including SOA server) must be bounced after modifying that one.
        </dd>
      </dl>
      This unit testing class uses a slightly different properties file, like this:
      <pre>
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=&lt;event-root xmlns="http://www.space-event.org">&lt;deeper-element>That is for real!!&lt;/deeper-element>&lt;/event-root>
# security.username=Oliv
# security.password=Secret
#
# Some room below, for user specific properties
# ...
      </pre>
      The provider.url property can be patched as the other ones already mentioned, using ${proxy.name} and ${soa.port.number}.
      <br>
      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.
      <br>
      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 <b>unit.test.event</b>. It goes along with the 
      properties file named <b>event.generic.properties</b>
    </p>
    <p>
      <h2>Running a suite of such tests in CruiseControl</h2>
      There is in the project ServiceUnitTest.jpr a class named <font face="courier">unittests.discovery.TestDiscoverer.java</font>,
      that relies on some properties file to know what test to run, in a given order.
      <br>
      There is also in the same workspace a project named ServiceUnitTestSample.for.CruiseControl, illustrating the point.
      <br>
      To use it, you <b>have to have</b> a file named <font face="courier">test.suite.definition.properties</font>, located at the
      root of the project containing the tests to run (i.e. sibling of the jpr file).
      <br>
      In case you need more than one test suite to live in the same project, you can do it by overriding the 
      <font face="courier">suite()</font> method.
      <br>
      <b>Example:</b>
      <pre>
public class DiscovererSample
  extends TestDiscoverer
{
  public static TestSuite suite()
  {
    return TestDiscoverer.suite(<b>"alternate.test.suite.definition.properties"</b>);
  }
}
      </pre>
      The parameter of the suite() method is the path to the properties file. It can be a fully qualified path.
      <br>
      If not parameter is provided to this method, then the file taken in account will be 
      <font face="courier">test.suite.definition.properties</font>
      <h3><font face="courier">test.suite.definition.properties</font></h3>
      Here is an example:
      <pre>
#
# 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
#
 ...
      </pre>
      <dl>
        <dt>Note:</dt>
        <dd>
          The properties <font face="courier">class.directory</font> and <font face="courier">delete.generated.class</font> are used if the property <font face="courier">use.asm</font> is set to <font face="courier">true</font>
          <br>
          This property is deprecated (its default value is false), as a result, the 3 first lines could be ignored (and not used).
        </dd>
      </dl>
      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.
      <br>
      Three exception though, some properties are generic for all tests: 
      <ul>
        <li type="disc">
          <b>classes.directory</b> This is the name of the directory where the generated test cases will
          be compiled. This must be a directory accessible for writing.
        </li>
        <li type="disc">
          <b>delete.generated.class</b> 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.
        </li>
        <li type="disc">
          <b>use.asm</b> 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, <i>without having to access the file system</i>. If this property is set to true (its default being false),
          then the two propeties mentioned above are useless and meaningless.<br>
          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.
        </li>
      </ul>
      <table border="1">
        <tr>
          <td valign="top">test.name.X</td>
          <td valign="top">Name your test (not used for now)</td>
        </tr>
        <tr>
          <td valign="top">test.description.X</td>
          <td valign="top">Description of your test (not used for now)</td>
        </tr>
        <tr>
          <td valign="top">test.class.X</td>
          <td valign="top">The name of the TestCase class to run. Semantically identical to the test@name attribute of the junit Ant task</td>
        </tr>
        <tr>
          <td valign="top">verbose.X</td>
          <td valign="top">If this is not clear, you need to talk to me (or your shrink)</td>
        </tr>
        <tr>
          <td valign="top">skip.X</td>
          <td valign="top">Allows you not to run a given test case, if set to "true".</td>
        </tr>
      </table>
      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.
      <br>
      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.
      <br>
      A sequence like 1, 2, 3, 4, 5 will build a suite of 5 tests.
      <br>
      A sequence like 1, 2, 4, 5, 6 will build a sequence of 2 tests.
      <br>
      A sequence like 2, 3, 4, 5 will build nothing.
      <br>
      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.
      <br>
      Example:
      <pre>
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
      </pre>
      This transition happens between test 3 and test 4.
      <br>
      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...)
      <br>
      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.
      <br>
      <i>Important:</i> Those XPath expressions <b>must</b> return one and only one node.
      <br>
      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:
      <pre>
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=<b>${worker.id}</b>
#
...
#
transition.from.xpath.4.1=<b>${worker.id}</b>
transition.to.xpath.4.1=//{urn:for-test}node-two
      </pre>
      The variable "worker.id" is first set, and then used.
      <br>
      Whatever begins with "${" and finishes with "}" is considered as a system variable.
      <br>
      You can also notice the <b>transition.from.literal.3.2=INIT-VALUE</b>. You can use literal values.
      <br>
      <b><i>There is also a special type of transition</i></b> that can be run <i>before</i> the first test,
      as an initialization. This would have the test index set to 0. It would look like this:
      <pre>
#
transition.to.file.0=transition.input.xml
transition.from.literal.0.1=RE-INITIALIZATION
transition.to.xpath.0.1=//{urn:for-test}node-one
#     </pre>
      Only literal values are supported for the "from" part, for obvious reasons (System variables could work, but this is not supported - yet).      
      <br><br>
      <font color="red"><b>Caution!</b></font> If you are intending to use those transitions, you need to make sure
      the files you manipulate are <u>writable</u> 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.
      <h3>Run a sample</h3>
      From JDeveloper, in the project ServiceUnitTestSample.for.CruiseControl, right-click on the class serviceunittest.ProjectTestDiscoverer, and run it.
      <h4>Internals</h4>
      Just for your information, here is how it works.
      <br>
      The <font face="courier">unittests.discovery.TestDiscoverer</font> is itself a TestSuite.
      As such, it has a method like
      <pre>
public static TestSuite suite() { ... }
      </pre>
      This method returns to whoever calls it the List of the TestCases to run.
      <br>
      The TestDiscoverer dynamically builds this list based on the properties file driving it.
      It is overriding the setUp() method to set the required System variables (like the jps-config location, the properties file to use for the test, etc),
      and possibly the tearDown() one, whenever a transition between tests is required.
      <br>
      The overriden class is compiled and injected in the class loader, and then added to the list of test cases.
      If the verbose property is set to "true" for a given test, the generated code will be displayed on the standard output.
      <br>
      Also notice that the test.class can be anything extending the junit.framework.TestCase class, not necessarilly the base classes we've provided.
      <br>
      <h4>Run from CruiseControl</h4>
      In your current build file, add a target like that one:
      <pre>
      &lt;target name="test-soa" xmlns:custom="antlib:oracle.anttasks">
        &lt;custom:test workspace="${basedir}/components/family/SomeWorkspace.jws">
            &lt;testProject regex="ProjectContainingMyTests">
                 &lt;fileset testDir="src">
                    &lt;patternset>
                       &lt;include name="**/*DiscovererSample*.java"/>
                       &lt;exclude name="**/.ade_path/**"/>
                       &lt;exclude name="**/util/**"/>
                       &lt;exclude name="**/*PUNIT*"/>
                     &lt;/patternset>
                 &lt;/fileset>
            &lt;/testProject>
        &lt;/custom:test>
      &lt;/target>
      </pre>
      This will run whatever matches '**/*DiscovererSample*.java', using the classpath set at the project level.
    </p>
    <hr>
    <address>Oliv did it.</address>
  </body>
</html>


 
 
Close
loading
Please Confirm
Close