Integration Testing Workflows

/ February 1, 2016
Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing.

In my last post I discussed unit testing code activities. Now that we’ve verified our custom activities behave the way we want we need to test the workflow as a whole to ensure they work together correctly. This is called integration testing. This is especially important for WF as much of the logic may be encompassed in out of the box activities and thus not have unit tests around them.

The best part is we test workflows just like code activities!

In our test init we will setup our base mock object.

Next, in our “Because” method we will wire up the call to our Workflow.

Finally, we write our test.

This is great for workflows that need to conform to a certain behavior and you want to test to verify it or the integration tests can serve as validation for user updatable workflows to ensure that any specific requirements are still maintained.

You can see this test in action in a sample project available on GitHub.

Unit Testing Workflow Code Activities

/ January 25, 2016
Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation.

Unit testing is a lot like going to the gym. When you first start out it’s miserable, you question why you’re putting yourself through it but over time you start seeing the results and realize you should have been doing it all along.

I’ve gone through all those phases in my development career and I’ve now reached the point that I couldn’t imagine writing code and not writing unit tests and it’s no different when using Workflow.

First, let’s talk about a few of keys to writing a good unit test and how code activities play into that:

  1. Make each test independent.
    1. Tests should not rely on the result of any other test. Code activities and the visual nature of workflows help to point out where you may be trying to do too much in your code.
  2. Test only one code unit at a time.
    1. Code activities know nothing about other code activities. All data is passed using in and out arguments. While you can still overload your code activities with lots of logic, you should be able to “smell” the bad coding practice.
  3. Mock external dependencies.
    1. Workflow offers a fantastic service location pattern called “Workflow Extensions” (more to come in a future post on this topic).

Writing unit tests for code activities is almost identical to any other unit tests except in how you call the code. In our “Because” method we’re going to use the “WorkflowInvoker” to call the code activity and pass in our mocked up data through the arguments. We’ll use our Loan example from my earlier post to illustrate.

In our test init we will setup our base mock object.

public void TestInit()
{
_result = new bool?();

_loan = new Loan
{
LoanAmount = 100,
DownPaymentAmount = 20,
CreditRating = 700,
HasCollateral = true
};
}

Next, in our “Because” method we will wire up the call to the code activity.

private void Because()
{
//Create a new instance of our code activity
var validateLoanIsCompleteActivity = new WorkflowWebApiExample.CodeActivities.ValidateLoanIsComplete();
//Create a new WorkflowInvoker instance.
var workflowInvoker = new WorkflowInvoker(validateLoanIsCompleteActivity);
//Create a new input argument dictionary
var InputArguments = new Dictionary<string, object>();
//Add our argument to the dictionary.
InputArguments.Add("Loan", _loan);
//Invoke the workflow and capture the result.
var resultDictionary = workflowInvoker.Invoke(InputArguments);
//Cast the result to the appropriate type.
_result = (bool)resultDictionary["Valid"];
}

Finally, we write our test.

public void Should_return_false_for_valid_if_loan_amount_is_0()
{
_loan.LoanAmount = 0;

Because();

Assert.IsFalse(_result.Value, "Expected to receive false when the amount was 0 but _result was true.");
}

It’s just that simple. There’s no real reason to not write tests for your code activities.

You can see this test in action in a sample project available on GitHub.

Projects to Watch: Orleans.Activities, Windows Workflow Foundation on Orleans

/ January 25, 2016
Orleans is a framework that provides a straightforward approach to building distributed high-scale computing applications, without the need to learn and apply complex concurrency or other scaling patterns. It was created by Microsoft Research and designed for use in the cloud.
Microsoft Orleans (GitHub)

I just came across a new GitHub project, Orleans.Activities, which combines Workflow Foundation with the Microsoft Research project, Orleans (most notably used by the backing services of Halo). Orleans is based on the actor model and allows developers to build complex highly scalable applications very easily.

Orleans.Activities seems like a natural fit for Orleans as the visual nature of Workflow will make these complex applications easier to understand and model the flow as well as leverage Workflow’s built-in support for long running workflows.

I will be keeping a close eye on this project and look forward to seeing where it goes.

Using Windows Workflow with Web API

/ January 19, 2016

When Windows Workflow Foundation was originally conceived, WCF was the “hot” web service technology for .NET developers. However, since then, the industry and Microsoft have moved toward RESTful services like Web API.

While Workflow does not have native support for Web API in the same way it does for WCF (although the Workflow dev team is interested in adding support) it doesn’t mean you can’t use workflows in your Web API service!

Let’s take a look at how we can add a workflow to our Web API service.

Example:

In this example we will use a simple workflow to evaluate a loan application and determine if we will approve it or not. We will be checking the following:

  1. Does the applicant have collateral?
  2. Does the applicant have a credit rating equal to or greater than 650?
  3. Does the applicant have a down payment of greater than 20%?

First, let’s create a “Loan” model and add a few properties.

Next, let’s create a simple code activity to verify that the application has been completed.

CreditAppAddNewCodeActivity

We’re going to add an “InArgument” to take in our “Loan” and an out argument to pass back whether it was “Valid” or not. The we’ll add some code to see if the properties have been filled out. After that we we will build the solution.

Next let’s create a new “xaml” workflow.

WebApiExampleNewWorkflow

First, we will add arguments to take in our loan model and pass back our result.

CreditAppWorkflowArguments

We will also add a variable for holding the “applicationComplete” variable.

CreditAppWorkflowVariable

We’re going to add a a few “FlowDecision” activities and wire them up to check our various conditions:

  1. Is the loan application complete?
  2. Is credit rating greater than or equal 650?
  3. Does the applicant have collateral?
  4. Is the down payment at least 20% of the loan amount?

CreditAppWorkflow

Right click on each activity and we will set the “Condition”

CreditAppExpressionEditor

In the end your workflow should look like this.

CreditAppWorkflowFull

Now that we have our Workflows created we can wire them up in our controller. It’s very simple.

Now, if we call our service with parameters that ensure success we get back true.

CreditAppTrue

And if we change our credit rating to ensure a denial we get back false.

CreditAppFalse

As you can see we can very easily add Workflow capabilities to our Web API service. We can also reuse these workflows completely unaltered in any .NET application, whether it be WCF, WPF or MVC. Best of all, the logic behind this app is visual and easy to understand.

I hope this shows that workflow can be used in any of your apps and not just big enterprise WCF apps.

This sample project is available on GitHub.

Tools I like: NCrunch

/ January 18, 2016

Writing unit tests can be hard. It doesn’t help that the built in tools around unit testing haven’t improved as fast as the rest of the IDE in the last few years.

Visual Studio can give coverage numbers but it doesn’t really give context which makes increasing coverage very difficult. Visual Studio and plugins like Resharper can execute tests but modifying code, executing the test suite and checking the results can be slow and cumbersome. There has to be a better way. Fortunately, we have NCrunch.

NCrunch is a Visual Studio plugin which runs your tests in the background and gives you results in near real time so you always know the state of the suite. Better yet, you will now get an indicator showing the coverage and pass/fail of every line of code:

White: Uncovered code

UncoveredCode

Red: Failing test

FailingCode

Green: Passing test

PassingCode

This allows us to quickly spot uncovered code. In the first week of my team having NCrunch we upped our code coverage by 20% because it was now very visible where we were lacking. It also makes refactoring a breeze because you instantly know when you’ve broken something.

To really appreciate the power of NCrunch though, you need to see it in action so I’ve put together a brief screencast of finding uncovered code, adding a unit test, seeing a failure and correcting it all without saving building or going to “Test Explorer.”

Pros:
  1. Easily shows uncovered code.
  2. Shortens the feedback loop when adding tests or making changes to the code.
  3. Encourages developers to write more unit tests
Cons:
  1. Code can go “green” even though you’re not exercising the code fully.
  2. Consumes a fair amount of resources and may not be great  for older machines.
  3. Odd licensing, where your key is good through versions based on the date of purchase and upgrade prompts can cause you to install an unlicensed version.

We’ve found NCrunch to be extremely useful and I think you will too.

http://www.ncrunch.net

Never forget to set workflow arguments again with the “RequiredArgument” attribute

/ January 16, 2016

It happens all the time, I create a new code activity, build it and drop it in the designer, run and BOOM runtime error. I forgot to set the argument. Even worse, sometimes you might have an activity that because of NULL checks or some other design reason does not throw any error and now you have an activity that does nothing and isn’t immediately apparent.

WorkflowArgumentMissing

Wouldn’t it be great if we could have thrown a build error? Well, the Workflow team has given us the answer in the form of the [RequiredAttribute]! Simply add it above the argument you want to validate.

RequiredAttribute

Now you’ll get designer and build time errors if the argument has not been properly set.

RequiredArgumentBuildError

It’s a small thing but it’s one more way to ensure you’re not introducing simple errors into your code.

I’ve added it to a sample project on GitHub.

Announcing my new developer blog

/ January 16, 2016

I love to learn about new technologies and development practices, but even more than that I love to spread that knowledge. This is why I’m launching my new developer blog “Code Coverage”! I will be posting on several different topics including: .NET tips and tricks, my insights on developer culture and my personal passion technology, Workflow Foundation.

I hope that you find this blog useful and if you have anything you want to see me post, shoot me an email or leave me a comment.

.NET Rocks 1236: Windows Workflow Foundation with Blake Helms

/ December 29, 2015

Check out my recent appearance on the .NET Rocks podcast where I talk through how Workflow has evolved into the latest version for .NET 4.6, with better visualization tools and a consistent interface that is easy to work with. The conversation digs into how Workflow separates work from flow – activities are code and flows are the relationships between them. This separation lets you see where there are holes in your decision-making system and helps keep code organized and focused. The question is, when wouldn’t you use Workflow?

https://www.dotnetrocks.com/?show=1236

Newer