miércoles, 21 de octubre de 2009

AgilePoint extensions unit tests

Hi again,
After a few months resting I am here again with a new interesting blog entry :-).
I am going to spend a few entries to talk about unit testing your AgilePoint extensions (AgileParts and AgileWorks basically).
When I started developing AgileParts one of the things I realise, is how much time I wasted testing my code.
I had to create a process to test the AgilePart in Envision, deploy the process, attach to corresponding w3wp process, and then, I can debug.
Too much time wasted getting the AgilePart in context for debugging, there must be a better way to do this.

In the next entries I am going to show the process I followed to create a Unit Testing Framework for AgilePoint that have saved me much time.

This is a summary of what I considere that is needed to get this framework:

  • Base test clasess for AgilePart and AgileWork tests.
  • IWFApi implementation to be used as a mock class.
  • IWFAdmin implementation (used in very specific implementations).
  • An easy mechanism to set context process variables and AgileParts/Works parametrization to allow testing multiple scenarios.
  • An extension of WFProcessInstance to be used as mock class in tests.
  • Several code snippets to increase the speed of coding even more :-)
Once I have this, I can create a new Unit Test in Visual Studio for my AgileParts in a few seconds.

The basic idea is to provide a mechanism to run AgileParts and AgileWorks without running processes in AgilePoint Engine, creating mock classes that simulate the behavior of the engine.

This is the code I need to test an AgileWork using my framework:

[TestMethod]
public void TestAgileWork()

{

WFAdmMock myMock = new WFAdmMock();

api.RunAgileWork(CreateDescriptor(CreateDescriptorWork), typeof(DynamicParallelActivity), GetWFManualActivity, GetWFProcessInstance, GetManualWorkItems, WFEvent.ASSIGN_WORKITEM, myMock);

}

protected Ascentn.Workflow.Base.WFAgileWorkDescriptor CreateDescriptorWork()

{

DynamicParallelActivityDescriptor desc = new DynamicParallelActivityDescriptor();

desc.Participant = "xxx";

desc.Name = "name";

desc.ID = "Test";

desc.DisplayName = "TestDisplay";

NameValue[] nvs = new NameValue[2];

nvs[0] = new NameValue("Task1", "user1");

nvs[1] = new NameValue("Task2", "user2");

desc.WorkItems = nvs;

return desc;

}


As you can see, I do not work much to create a test.

If you are interested in this ... comments are welcome.

sábado, 8 de agosto de 2009

ClientData: How to configure UI behavior

Maybe yo have seen ClientData property in WFManualWorkItem class and you wonder what this property is for.

Well, let's take a look at WebForm AgileShape(AgileWork).

If you configure it it Envision, you can configure a URL (with context parameters), and you can configure the controls behavior, you can set if you want a control to be readonly, hidden,...

If you do that in a template and run the process, you can get the instance of the WFManualWorkItem in runtime and you will see that the content of ClientData property is the configuration that you have set in Envision.

Using the AgilePoint wep application template in Visual Studio you will see that controls behavior is applied automatically by the WFWorkSheetPage class.

So, what's the idea behind this?

Te idea is provide a mechanism to pass UI configuration from design time to UI runtime, this is the information flow:

  • Designer sets UI configuration in Envision.
  • This configuration is saved as AgileWork descriptor configuration.
  • At runtime AgileWork takes configuration and (in an event where the WFManualWorkItem already exists, for example AssignWorkItem) the AgileWork writes the content of ClientData for each workitem.
  • When the UI (in our sample the aspx page) is presented, the UI code retrieves the WFManualWorkItem(using the WorktemID) and applies the configuration that has been set at design time and written at runtime in AgilePoint server.
I think this is a powerful approach, don't you think so?

domingo, 26 de julio de 2009

AgileWorks

Today I am going to spend a dew minutus talking about AgileWorks.
What is an AgileWork?
An AgileWork is made, basically, by 2 classes, one for runtime(the class that inherit from AgileWork) and one for design time, the class that inherits from WFAgileWorkDescriptor.

If you create an AgileWork project in Visula Studio you will see this two classes.

Once you have them you can start creating your AgileWork :-).

The design time time class has similar funtionalities to the corresponding AgilePart descriptor but the runtiome class has much more functionalities.

The main purpose of an AgileWork is to be used in manual task, that is,when the process has human interaction, but in theory you should use an AgileWork when you want to subscribe to events at runtime.

There is a list of events you can subscribe to:
  • Enter activity instance.
  • Leave Activity Instance.
  • Assign WorkItem
  • Complete WorkItem
  • ...

Let's say that we want to get the user assigned to a task at runtime.

This can be easily achieved by siubscribing to EnterActivityInstance and changing the value of the participants field.

I will provide sample code in next entries.

For me, the best idea behind AgileWorks is the fact that you can have several WorkItems in one activity. You can assign multiple tasks and the process drawing has only one shape for this step.

That is what Parallel Approval (and others) shape does, it creates several workitems(one for each user) when the engine arrives to this activity. With this approach the drawing is easier to understand.

The same idea is applied when you assign a task to several users, when you configure a manuall task to be assigned to "user1;user2;user3" three workitems are created.

This is the first entry where I talk about events inside AgilePoint, but this issue will need a monographic :-), there are many places in AgilePoint where you can handel engine events. AgileWorks, AgileStub, AgileConnector,...

You can have complete control over the behavior of the engine. You just need coding.

sábado, 18 de julio de 2009

Here again :-)
I was thinking about writing abou asynchronus AgileParts but I have found this AgilePoint blog where you can find a description of this functionality so I will write about another funtionality.

sábado, 4 de julio de 2009

AgilePoint extensibility

First we are going to talk about AgilePoint extensions:
  • AgilePart
  • AgileWork
  • AgileStub
  • AgileConnector
Extensibility is the main advantage of AgilePoint so this is going to be the main issue in this blog, so if you are interested in out of the box functionalities do not waste your time her :-).

AgileParts

This is the first extension point that we are to talk about.

What is an AgilePart? is a method that the engine is going to call at runtime passing the parameters that you have gathered using the WFAgilePartDescriptor that you have created in the AgilePart project template in Visual Studio.

Easy :-), but what does it mean?

When you create an AgilePart project, you have 2 main classes, AgilePart and AgilePart descriptor.

Every method that you decorate with an WFAgilePartDescriptor is going to be exposed as an AgilePart in Envision and the WFAgilePartDescriptor is going to be exposed by Envision in the right side property grid to gather configuration from Business User .

When the engine arrives to the AgilePart at runtime, the method is called and you get the actual values of the configuration and you can do whatever you want with them.

So what is the approach AgilePoint have?

AgilePoint provides a mechanism to gather information from business users at design time and this configuration is used at run time to make technical stuff that AgileParts(and AgileWorks) isolate.

Stop reading for 10 miuntes and thik about it...

This is really powerful, you can use a standard and extensible interface, Visio and .Net, to get all configuration that you need for your runtime, and this configuration can be as user friendly as you can imagine, and you can use .Net platform at runtime to connect to other systems and run your technical stuff.

The key point here is expose your technical needs translatig them to user friendly language, for example if youare going to call to your ERP using whatever protocol and parameters,... that you need(as you can see I am not an expert in ERP systems :-)), the Business User's should not care about this technical needs, he should care about where to get the amount of his invoice, the name of the client,...

So your work as IT guy is provide the interface to configure this call to the ERP and the user at design time should not care if your ERP is SAP,Axapta a database or csv file, this is your responsability.

Welcome to this blog where we are going to talk about AgilePoint BPMS trying to show how to get the best from this platform.

If you want an introduction you can go to Ascentn's web page.