Monday, September 3, 2007

Automation testing or simulation with K2.net 2003

I initially published this at http://k2underground.com/blogs/articles/archive/2007/08/21/automation-testing-or-simulation-with-k2-net-2003.aspx, but I figured this would be a good starting point for my K2.net Blog.

This article will show how to create automated unit tests which can be used to exercise K2.net workflow process in both ASP.net and InfoPath. Creating automated testing or simulation with K2.net 2003 may seem difficult to do but is easy when using Visual Studio 2005 Test Projects. Creating unit tests with Visual Studio is no different than creating a custom web page that uses the K2ROM to finish a worklist item that has been assigned to a user. In this case instead of embedding code into an .aspx code behind we are going to put the code into a test method.

2. Create a K2.net Process
The following K2.net process is a standard approve/deny process. This particular screenshot shows an approval process using ASP.net. This process would be initiated by a custom ASP.net page or a K2.net 2003 SmartForm PlanPage. There would then be a second web page which the Manager would use to approve the process instance. Finally an email would be sent out based on the Manager’s decision.

An assumption is made that the reader knows how to create a basic workflow. The specific details of setting destination users, configuring line rules, configuring email, etc. will not be covered.






2.1 Adding a Test ID Data Field
The Visual Studio Test Project will require an identifier to correlate the K2.net process instance with the test instance. K2.net generates an identifier called a Serial Number that uniquely identifies every process, activity and event instance. To achieve this we will add a Data Field to the Process by going to the Properties of the Process, clicking on Data Fields and adding a string type called AutomatedTestID. The value will be generated by the Unit Test and set through the K2ROM which will be discussed later.


2.2 Add Approval Data Field
For the purposes of this article we will add an Approve Data Field to the Manager Approval activity. This will be used by the manager to approve or deny the workflow.









3. Create Visual Studio Test Project
Start Visual Studio 2005 and select File, then new Project. In the New Project window select the programming language of choice (in this case C#) and the select the Test option. Within this select Test Project and place the project in a location.





3.1 Configuring the Test Project
The following will be created for you by default.

First rename the default class UnitTest1 to SimpleWorkflowTest by right clicking the filename in the Solution Explorer and selecting rename. After renaming the file you will be prompted to rename all references; select yes.










Next add a reference to the K2ROM by right clicking the References node in the Solution Explorer and selecting Add Reference. In the Add Reference window select the Browse tab and go to \Program Files\K2.net 2003\Bin and select the K2ROM.dll.




The resulting project should look like the following.















3.2 Create Test Methods
To simulate this workflow we need to create two test methods. Note the methods must be decorated with the [TestMethod] attribute and the class with [TestClass]. If these are not present neither the class nor its methods will be used when the unit test is executed. First rename TestMethod1() to SimpleApprovalTest(). Next add two method stubs one called StartSimpleWorkflow() and the other called ManagerApproval(). Notice that both of these methods have not been decorated with [TestMethod] attribute. They will be executed by Visual Studio because SimpleApprovalTest() is the entry point and has the [TestMethod] attribute.
3.3 SimpleApprovalTest Method
Once we have our stub set up, a unique identifier needs to be generated for the unit test instance which will be used to correlate to the K2.net process instance. Modify SimpleApprovalTest() to generate a GUID and pass that value down into both StartSimpleWorkflow() and ManagerApproval().

[TestMethod]
public void SimpleApprovalTest() {
//Create Test Instance GUID
Guid testInstance = new Guid();

//Start the process
StartSimpleWorkflow(testInstance);

//Give K2 server time to create process instance
System.Threading.Thread.Sleep(2000);

//Approve the process
ManagerApproval(testInstance);
}

Both of these methods will need to have their signatures modified to accept the GUID.

private void StartSimpleWorkflow(Guid testInstance) {

}

private void ManagerApproval(Guid testInstance) {

}

Note the System.Threading.Thread.Sleep(2000) was added to give K2.net server a little time between activities. Depending on your testing server performance, this value may need to be modified or this line could be completely removed.

3.4 StartSimpleWorkflow Test Method
Add the following statement using SourceCode.K2ROM; in the class.

Add the following code to the StartSimpleWorkflow(Guid testInstance) method which will create a new process instance using the K2ROM. This method opens a connection to the K2.net server, sets the GUID to the process instance and folio name, and finally starts the process.

private void StartSimpleWorkflow(Guid testInstance) {
string connectionString;
string k2Server;
string processName;
Connection conn = new Connection();

try {
//Recommend moving thses values to app.config file
connectionString = "CONNECTION STRING";
k2Server = "SERVER NAME";
processName = "SimpleApproval\\SimpleApproval";

//Open K2 Connection
conn.Open(k2Server, connectionString);

//Create Process Instance
ProcessInstance process = conn.CreateProcessInstance(processName);

//Set the test instance id
process.DataFields["AutomatedTestID"].Value = testInstance.ToString();

//Set K2 Folio Name
process.Folio = "Test Simple Approval " + testInstance.ToString();

//Start the process
conn.StartProcessInstance(process);
}
catch (Exception ex) {
// failed validation
Assert.Fail("The process failed: " + ex.Message);
}
finally {
conn.Close();
}
}

3.5 ManagerApproval Test Method
In this method a connection is made to the K2.net server and the Worklist for the Manager is opened. This is done by using the WorklistCriteria object to query for the WorklistItem that has test instance GUID set in its process data field. This is done by using a WorklistCriteria with a filter. When the WorklistItem is returned the activity instance data field is set to “approve” and the WorklistItem is subsequently finished.

private void ManagerApproval(Guid testInstance) {
string connectionString;
string k2Server;
Connection conn = new Connection();
Worklist workList;
WorklistCriteria workListCriteria = new WorklistCriteria();

try {
//Recommend moving thses values to app.config file
connectionString = "CONNECTION STRING";
k2Server = "SERVER NAME";

//Open K2 Connection
conn.Open(k2Server, connectionString);

//Retrieve the test manager's worklist items
workListCriteria.AddFilterField(WCLogical.And, WCField.ProcessData, "AutomatedTestID", WCCompare.Equal, testInstance.ToString());
workList = conn.OpenWorklist(workListCriteria);

//Find the worklist item with the test identifier in it
foreach (WorklistItem workListItem in workList) {

//Set the process for approval
workListItem.ActivityInstanceDestination.DataFields["Approve"].Value = "Approve";

//Finish the worklist item
workListItem.Finish();
}
}
catch (Exception ex) {
// failed validation
Assert.Fail("The process failed: " + ex.Message);
}
finally {
conn.Close();
}
}

3.6 More Test Methods
More test methods could be created in a similar fashion. For instance a similar test method could be created for the denial path. As well if the workflow had multiple steps every step in the process could have a method created and chained to one another to fully test the entire workflow and every possible path it could take.
4. Deployment
It is highly recommended that this not be done on a production K2.net server. A K2.net testing server should be used to run the unit tests on. The reason is that these test process instances will be intermingled with production instances. Having these instances in there will subsequently throw off or dilute reports provided in the K2.net Workspace.

Deployment of the SimpleWorkflow would be the same as any other K2.net process using the Export functionality in K2.net Studio.

5. InfoPath Testing
It is possible to test InfoPath process in K2.net visual studio as well. In the Visual Studio Test Project, add a reference to the InfoPathService web service.

Change the StartSimpleWorkflow(Guid testInstance) method and remove all of the code associated to the K2ROM. Instead call the SubmitInfoPathData method of the InfoPathService web service. Generate the XML for the InfoPath form and pass that into SubmitInfoPathData webmethod. To get a sample of this XML, open an InfoPath that has been K2.net enabled and save it locally. Then open the .Xml file in a text editor and copy the Xml into the Visual Studio. That Xml string can be passed into SubmitInfoPathData.

Next in ManagerApproval(Guid testInstance) remove the following line of code.

workListItem.ActivityInstanceDestination.DataFields["Approve"].Value = "Approve";

Instead use this line of code to retrieve the XML for the InfoPath Form.

string infoPathXml = workListItem.ActivityInstanceDestination.XmlFields["K2InfoPathSchema"].Value;

Once the Xml has been retrieved, modify it (setting it to Approved) and call SubmitInfoPathData webmethod again passing in the Xml. Do not set the Xml back into workListItem.ActivityInstanceDestination.XmlFields["K2InfoPathSchema"] because this would not accurately test the process as InfoPath will always call the web service.
6. Conclusions
Very sophisticated testing processes can be done in this manner testing multiple steps and every permutations of the workflow. Load testing can be done as well by creating multiple unit test instances to identify bottlenecks in the workflow process. Bottlenecks could be sometimes be hardware specific, a connection to an external system may be too slow, tables in a database require indexes, etc. Using this methodology it is possible to completely test your K2.net processes without writing any ASP.net or InfoPath front-ends. This will create a highly decoupled solution and is considered a best practice.

No comments: