Thursday, April 18, 2013

How to write your first Platform Automated Test


Objective of this guide on platform test is to enable users to start with automating platform test scenarios using WSO2 Test Automation Framework. This will be a generic guide written based on ESB and Data services servers. We expect readers of this document to have basic knowledge of TestNG framework. You can refer to TestNG documentation to get initial knowledge required.

What it mean by platform

WSO2 product platform compromise of a set of products, which are integrated to support enterprise use cases. For an example governance platform compromise of Governance registry, CEP, Business Activity Monitor and Identity server which provides SOA governance, social enterprise, analytics, lifecycle management capabilities. In the point of automation we call a specific set up a platform, if one or more products are integrated to implement business use case.

Platform Tests

Automation test framework has been designed to conduct testing of platform scenarios
on a complete, integrated system to evaluate the system's compliance with its desired
requirements.Test scenarios will be mainly based on possible applications which can be
developed using WSO2 product platform.

Scenario to be Automated

SOAP service named student data service which will be deployed on WSO2 Data Service Server which is again fronted by ESB proxy to provide RESTful API to manage student resource. The test case will deploy data service on DSS and synapse artifacts on ESB then it invokes the RESTful API exposed via ESB and perform basic GET, POST, DELETE, PUT methods on student resource.

WSO2 library article written by Amila Suriarachchi describe the end to end scenario that is going to automated here.


Where to Add Platform Tests

You checkout and use WSO2 Platform Automated Test Suite to add the test case.


org.wso2.carbon.automation.platform.test.scenarios module can be used to implement platform automated tests.

Download Test Artifacts
Download artifacts required for the scenario from http://wso2.org/files/sample_10.zip you can find the artifact download link in above mentioned OT article also.

Configure Test Environment
  • Navigate to org.wso2.carbon.automation.platform.test.scenarios module and start by adding a new test package.
e.g.
platform-integration/platform-automated-test-suite/1.1.2/org.wso2.carbon.automation.platform.test.scenarios/src/test/java/org.wso2.carbon.automation.platform.scenarios/esb

  • Then go to automation.properties file under src/test/resources and edit following properties.
  1. product.list=DSS,ESB
  2. execution.environment=platform
  3. execution.mode=user
  4. dss.host.name=localhost
  5. dss.http.port=9764
  6. dss.https.port=9444
  7. esb.host.name=localhost
  8. esb.http.port=9763
  9. esb.https.port=9443
  10. esb.nhttp.port=8280
  11. esb.nhttps.port=8243
  12. database.driver.name=com.mysql.jdbc.Driver
  13. jdbc.url=jdbc:mysql://localhost:3306
  14. db.user=root
  15. db.password=root
  16. db.name=STUDENT_DB


You can set ports and host names of DSS and ESB servers according to your server settings.

Framework uses mysql as the default DB for data services. So you need to set connection settings as illustrated in #13 to #16.

  • Import your keystores in to wso2carbon.jks at org.wso2.carbon.automation.platform.test.scenarios/src/test/resources/keystores       You don’t need to do this step if you are using default keystores in WSO2 products.

  • Update admin credentials in userList.csv and tenantList.csv files at src/test/resources with your admin credentials. You don’t need to update other user details. Test framework will automatically populates user list to products. It identify the server list by reading product.list property defined in automation.properties file. These users will be used in various test cases.  Note that all users have permission to read, write, delete and authorize registry space. in terms of other access privileges they are approximately equal to admins. However don’t have super admin privileges.

  • Now navigate to endpintlookup.xml at src/test/resources and put following entry
    "http://localhost:9765/services/StudentService/"


Here we define address endpoint of student data service in endpointlookup.xml. Endpoint lookup is used to replace the endpoints defined in synapse configuration based on the test execution environment. You need to invoke the endpoint replacement functions before updating synapse configuration via test.


Copy Test Artifacts to Framework Artifact Repo

  • Copy StudentService.dbs into src/test/resources/artifacts/DSS/dbs/rdbms/MySql and student.sql into src/test/resources/artifacts/DSS/sql/MySql




Start Writing Your First Platform Test

please refer to methods comments for further clarifications.

 /**  
  * Implement the scenario discussed in  
  * http://wso2.org/library/articles/2012/10/implementing-restful-services-wso2-esb  
  */  
 public class RestFullApiTestCase {  
   private static final Log log = LogFactory.getLog(RestFullApiTestCase.class);  
   private DataServiceBaseTest dataServiceBaseTest;  
   private ESBBaseTest esbBaseTest;  
   private URL url;  
   /**  
    * Initialize test environment by creating instances of DataServiceBaseTest and ESBBaseTest classes, these classes  
    * provide required utility functions such as upload data service, update and revert synapse configuration etc..  
    * <p/>  
    * And resource URI is constructed by getting service URL of esb instance in esbBaseTest.  
    *  
    * @throws Exception - if initialization fails  
    */  
   @BeforeClass(groups = "wso2.esb", alwaysRun = true, description = "initialize test environment")  
   public void testInitialize() throws Exception {  
     esbBaseTest = new ESBBaseTest();  
     dataServiceBaseTest = new DataServiceBaseTest();  
     url = new URL(esbBaseTest.esbServer.getServiceUrl().  
         substring(0, esbBaseTest.esbServer.getServiceUrl().lastIndexOf("/")) + "/students/003");  
   }  
   /**  
    * Execute student.sql on mysql instance which specified in automation.properties file. Then deploy the data service  
    * located at DSS artifact repository.  
    *  
    * @throws Exception - if data service deployment fails  
    */  
   @Test(groups = "wso2.esb", description = "deploy student data service")  
   public void testDeployStudentService() throws Exception {  
     String serviceName = "StudentService";  
     List<File> sqlFileLis = new ArrayList<File>();  
     sqlFileLis.add(dataServiceBaseTest.selectSqlFile("student.sql"));  
     dataServiceBaseTest.deployService(  
         serviceName, dataServiceBaseTest.  
         createArtifact(ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION + "artifacts"  
                 + File.separator + "DSS" + File.separator + "dbs" + File.separator  
                 + "rdbms" + File.separator + "MySql" + File.separator  
                 + "StudentService.dbs", sqlFileLis));  
     log.info(serviceName + " uploaded");  
   }  
 /**  
    * updateESBConfiguration(OMElement synapseConfigOM)  
    * will deployed the artifact defined in the synapse configuration (proxy, endpoints, sequence, message store, etc..)  
    * using admin services API. Framework will go through the configuration and deployed each synapse artifact separately.  
    * If synapse artifact with same name exists in the system, it is deleted delete existing one and redeploy new one.  
    *  
    * @throws Exception - if update of synapse configuration fails.  
    */  
   @Test(groups = "wso2.esb", description = "update synapse config", dependsOnMethods = "testDeployStudentService")  
   public void testUpdateSynapseConfig() throws Exception {  
     String synapseConfigPath = ProductConstant.SYSTEM_TEST_RESOURCE_LOCATION + File.separator +  
                   "artifacts" + File.separator + "ESB" + File.separator + "synapseconfig" +  
                   File.separator + "config67" + File.separator + "synapse.xml";  
     EsbEndpointSetter esbEndpointSetter = new EsbEndpointSetter();  
     OMElement synapseConfigOM =  
         esbEndpointSetter.setEndpointURL(new DataHandler(new URL("file://" + synapseConfigPath)));  
     esbBaseTest.updateESBConfiguration(synapseConfigOM);  
   }  
   /**  
    * Add new student by sending POST request to student resource.  
    *  
    * @throws Exception - if POST request fails.  
    */  
   @Test(groups = "wso2.esb", dependsOnMethods = "testUpdateSynapseConfig", description = "Add new student")  
   public void testAddNewStudent() throws Exception {  
     String addPayload = "<p:Student xmlns:p=\"http://ws.wso2.org/dataservice\">\n" +  
               "   <p:name>tharindu</p:name>\n" +  
               "   <p:email>tharindu@gmail.com</p:email>\n" +  
               "   <p:age>16</p:age>\n" +  
               "   <p:class>8B</p:class>\n" +  
               "   <p:average>83.45</p:average>\n" +  
               "</p:Student>";  
     Reader data = new StringReader(addPayload);  
     Writer writer = new StringWriter();  
     HttpURLConnectionClient.sendPostRequest(data, url, writer, "application/xml");  
   }  
   /**  
    * Check whether the newly added student is exits by sending GET request.  
    *  
    * @throws Exception - if GET request fails.  
    */  
   @Test(groups = "wso2.esb", dependsOnMethods = "testAddNewStudent", description = "get newly added student")  
   public void testGetStudent() throws Exception {  
     HttpResponse response = HttpURLConnectionClient.sendGetRequest(url.toString(), null);  
     assertTrue(response.getData().contains("<Student xmlns=\"http://ws.wso2.org/dataservice\">" +  
                         "<RegistrationNumber>003</RegistrationNumber>" +  
                         "<Name>tharindu</Name><Email>tharindu@gmail.com</Email>" +  
                         "<Age>16</Age><Class>8B</Class><Average>83.45</Average>" +  
                         "</Student>"), "new student has not been added");  
   }  
   /**  
    * Update the student by sending PUT request to student resource. Then verify the whether the student is updatd by  
    * sending GET request to student resource.  
    *  
    * @throws Exception - if PUT request fails.  
    */  
   @Test(groups = "wso2.esb", dependsOnMethods = "testGetStudent", description = "update student")  
   public void testUpdateStudent() throws Exception {  
     String updatePayload = "<p:Student xmlns:p=\"http://ws.wso2.org/dataservice\">\n" +  
                 "   <p:name>amila</p:name>\n" +  
                 "   <p:email>amila@wso2.com</p:email>\n" +  
                 "   <p:age>16</p:age>\n" +  
                 "   <p:class>8A</p:class>\n" +  
                 "   <p:average>67.89</p:average>\n" +  
                 "</p:Student>";  
     Reader data = new StringReader(updatePayload);  
     Writer writer = new StringWriter();  
     HttpURLConnectionClient.sendPutRequest(data, url, writer, "application/xml");  
     System.out.println(writer.toString());  
     HttpResponse response = HttpURLConnectionClient.sendGetRequest(url.toString(), null);  
     assertTrue(response.getData().contains("<Student xmlns=\"http://ws.wso2.org/dataservice\">" +  
                         "<RegistrationNumber>003</RegistrationNumber>" +  
                         "<Name>amila</Name><Email>amila@wso2.com</Email>" +  
                         "<Age>16</Age><Class>8A</Class><Average>67.89</Average>" +  
                         "</Student>"), "new student has not been updated");  
   }  
   /**  
    * Delete the student by sending DELETE request to student resource. Then verify the whether the student is deleted by  
    * sending GET request to student resource.  
    *  
    * @throws Exception - if DELETE request fails.  
    */  
   @Test(groups = "wso2.esb", dependsOnMethods = "testUpdateStudent",  
      description = "delete student and try to get the student again")  
   public void testDeleteStudent() throws Exception {  
     HttpURLConnectionClient.sendDeleteRequest(url, null);  
     HttpResponse response = HttpURLConnectionClient.sendGetRequest(url.toString(), null);  
     assertTrue(response.getData().contains("<Students xmlns=\"http://ws.wso2.org/dataservice\"/>"),  
           "new student has not been deleted");  
   }  
   /**  
    * Undeploy data service after the executing all test methods.   
    * cleanup() will remove all deployed synapse artifacts.  
    *   
    * @throws Exception  
    */  
   @AfterClass(alwaysRun = true)  
   public void deleteService() throws Exception {  
     dataServiceBaseTest.deleteService("StudentService");  
     esbBaseTest.cleanup();  
   }  
 }  


To run the test class you have to add your test classes in testng.xml which is at src/test/resources

 <suite name="PlatformTestSuite" parallel="false">  
   <listeners>  
     <listener class-name="org.wso2.carbon.automation.core.PlatformExecutionManager"/>  
     <listener class-name="org.wso2.carbon.automation.core.PlatformSuiteManager"/>  
     <listener class-name="org.wso2.carbon.automation.core.PlatformAnnotationTransferManager"/>  
     <listener class-name="org.wso2.carbon.automation.core.PlatformTestManager"/>  
     <listener class-name="org.wso2.carbon.automation.core.PlatformReportManager"/>  
   </listeners>  
   <test name="Platform-test-scenarios" preserve-order="true" verbose="2">  
     <classes>  
       <class name="org.wso2.carbon.automation.platform.scenarios.esb.RestFullApiTestCase"/>  
     </classes>  
   </test>  
 </suite>  


How to Execute the Test

Note that all testNG listeners implemented in automation framework need to be registered in testng.xml

You can execute the test inside the module itself using maven surefire plugin or use platform automated test suite (wso2pats) to get the test executed on product setup.

To execute test using maven

  1. Start ESB and DSS servers.
  2. Make sure mysql server is running.
  3. The run the below command
    1. mvn install -DskipTests=false

You can find the surefire reports at target/surefire-reports directory.

To execute test using platform automated test suite

  1. Build the test by skipping tests.
    1. mvn install -DskipTests=true
  2. Then go to /platform-automated-test-suite/version/distribution directory.

  1. Now build the distribution - mvn clean install
  2. Go to distribution/target directory.
  3. You will find the wso2pats-1.1.x.zip distribution.
  4. Extract it and follow the instructions available at INSTALL.txt file.

Running Test on Different Environments
Once you write a test case you can run that test case in different environments. Just need to change the automation properties which can be found src/test/resources directory.


Executing test on integration Environment as a tenant
By default test runs on the product platform environment on user mode. By changing following properties in automation.properties file, users can execute the same test in product setup on tenant mode.

stratos.test=true  
#execution.environment = integration|platform|stratos  
execution.environment=stratos  
#execution.mode = user|tenant|all  
execution.mode=tenant  
port.enable=true  
carbon.web.context.enable=false  
builder.enable=false

Executing as a tenant
if you want to run the test as a tenant. setting below will execute the test as tenant.
execution.mode=tenant  

Executing test on cloud platform( Stratos)
if you want to run your test class against cloud platform,  change setting as below.

stratos.test=true  
execution.environment=stratos  
execution.mode=tenant  

#Stratos server details  
esb.service.host.name=esb.stratoslive.wso2.com
dss.service.host.name=data.stratoslive.wso2.com



































No comments: