Always write unit tests from get go

‘Always write unit tests from get go’, this is nothing new. If you are following TDD pattern then it is the default style. But when we develop an application which need to be delivered in a short time frame, if you do not have TDD background and testing is not the first class citizen in the programming tool set, before you know it, product will be delivered with no tests. This is always the case if there is no one bugging you about unit tests. 

Let’s talk about building a brand new application. Most of the time, when we develop a brand new application, our application will be very simple compared to what we end up with in three or four years down the road. Most of the time, our initial applications are very simple, which does nothing but bring data from back end and display it in the front end. Nothing much to it. When you have four or five line methods, why would you want to write unit test for it? It is a very bad assumption. You might start with this four line and as the application start growing these four lines might end up becoming twenty to forty lines (of course you might end up re factoring), you increased the complexity 10 fold. Now try to write unit tests and you will be stuck. There might some dependency that need to be removed and need to re factor the code so that we could even start unit testing. Now, unit testing becomes an explicit task which is going to consume time and effort. If you would have written the unit tests as part of initial development then as we add more code to it, our tests will also evolve and when we get to this twenty or forty line of code, there will be plenty of supporting unit tests for it. When someone is trying to modify this forty line method, it has good unit test to back them up so that they know they are not breaking any existing code.

One of the very important benefit of the unit testing which most of the people forget is that it can show you your design flaws very early on. If you are not following SOLID pattern then writing testing is little difficult. We always need to develop application in a loosely coupled model. All the dependencies should be injected into the code, which lends itself to a very maintainable software. If you were writing unit tests early on and if you were stuck on a place where you cannot do unit test, then you have a hard dependency problem or breaking one of the SOLID pattern. Since this problem identified early on, we can change the design to make it testable, we also reduced the complexity during the course of re-factoring. This is a great benefit of adding unit tests in the green field development. Write unit test for any and all the public methods, someone will thank you when they have to add a new feature to the same code after four years.

I hear people say, ‘I will come back and re factor the code and add unit tests’. Trust me when I say this, you are not coming back to re factor, you will have some other better things to do and never will have time to do it. Even if you were to come back to the code, how are you going to justify the task that could have been done in the first time itself? So here is a rule of thumb, if you ever say, ‘ I will come back to code to do something’, then you are knowingly adding tech debt to the code. Don’t just say it, do it. Do the re-factoring add unit tests, take extra effort and do it.  If it take some extra time to do it, I will ask you to talk to the managers and tell them the benefit of the re-factoring. If the managers do not understand (I really hope it is not the case), reach out to the technology leaders of your team. They will help you make the case.

Advertisements

Testing in Angular World

 

This has been a hot topic for me lately. I covered testing AngularJS in couple of blogs but over the time I noticed people who are coming from .Net world who are not used to TDD model still fall back to the old style development that is without tests or tests have been added after the fact. I think, either of the approach is totally wrong. Testing is first class citizens in AngularJS and we should treat them that way. I want to go over couple of argument I got when I asked them about why there are no tests or not following TDD and lets discuss about it. I will try to answer the best of ability.

We are still learning AngularJS so I can’t write unit tests.

Ok it seems very valid point. I would strongly recommend understand and learn how to do tests first. Testing in Angular is simple and straight forward. I am going to focus on testing in the coming blogs. Angular support both unit testing and end to end testing (e2e) testing. It is easy to learn and get going fast. First understand AngularJS concepts like $scope, $http and others then learn how to mock them, the rest is nothing but writing simple tests. The bottom line, if you are trying to learn AngularJS, learn testing along with basic concepts and then go into the details of AngularJS features.

Now going back point made, if you want to do something and you do not know how to do it in AngularJS then you can not write test for it. Well that is not 100% true. If you are following TDD model, then once you get the requirement that you are trying write code for, you are suppose to write the test first. Now that you already know how to write test, go ahead and write the test first and then try to do the implementation. When you are trying to implement, you may run into problems, then modify the tests as you make progress to fit the model you are writing. This is true in end to end testing as well (e2e), you might have end to end test against a form and as you learn you realize that you need data table, change the e2e test for it. But write the test first. It will help. Again, with the tests, even when you are learning, it catch the unexpected errors that you might make when experimenting with new concepts.

We can’t write tests because there is no logic in the code.

Excellent point, AngularJS is used to develop client side code. So if you are developing application properly, client side should be as dumb as possible. So in theory, we will have MVC pattern applied to both client side and server side. So all the complex business logic will be in the server side controller. Since you do not have complicated logic at client side, client side code should be very simple. Normally when we start out the client side code will be very simple, we might make a webapi call to get some data, bind them to the variables and that is it. So for that we do not need any tests. Trust me when I say this, that is how all the projects start. Always they are very simple in the beginning and as project start to grow, you will have more complex logic in it and at that time, it will be difficult to add test to it.

In the above scenario, my suggestion is to add unit tests to all the functions you might add to client side code, even if it is single line assignment statement. You will also agree, it is easy to write test cases of single line assignment statement, so go ahead and add the tests for it. It might seem silly, but now when you run the test, you have code coverage for the functions you have written. The benefit comes in the next iteration you are asked to add some logic to that method with simple assignment. You already have tests so you know why that function exists to start with and with that understanding you can add more tests to support new functionality without breaking the old ones. In this case, you are trying to understand what that function suppose to do since you might not have written the code, so you do not know what it was suppose to do. With tests, it is easy to see the scenarios and understand what exactly those methods suppose to do. It gives the confidence in your change you are making.

AngularJS provides not only unit testing, it also gives e2e testing. So even if there are no logic in the client side, you are working with the data coming from server to display data. So you can write tests for it. Write your e2e test with mock data and verify if the UI elements display the data as it suppose to be. The cases where the developer thinks there is no logic in the client side, then you will have more e2e tests than unit tests.

Angular JS – 10 (End to End Testing – Karma)

In the previous blog we looked at what is need to build a end to end test and run those test manually. In this blog, we will see how we can run this automatically in the background. The good thing is, there is nothing special end to end testing rather how you run it. Hopefully you got something from my previous blog on how to write an end to end test.

If you haven’t gotten the Intro to Karma project from GitHub, please do get it. It has the sample code and everything needed to run automated end to end test. Couple of things you need to run end to end test using Karma. You need a web server so in our case we will be using ‘node’. If you do not have it, please install it. Once you have node, you need to install Karma. Now that we have the sample code and required components like node and Karma, lets see how we can run Karma to test end to end tests.

To run karma, one would need a configuration file. Now if you got the introduction to karma project  from the GitHub then it comes with a simple configuration file. We will use that to run the end to end test. So lets first run the test with the configuration file already in the project. It is a two step process to do automated end to end tests.

  • Start the node server. Navigate to the location of the project. From the root directory, in DOS/terminal

node test\scripts\web-server.js

  • Now that node is running, lets run the Karma in another DOS/terminal from the root location of the project

karma start config\karma-e2e.conf.js

After the two steps, the test should run only once, it will not wait for code change and keep running the tests. We will modify that little later.

image

If you notice, we run Karma pointing to Karma.e2e.conf.js. Lets look at the configuration file.

1 basePath = '../'; 2 3 files = [ 4 ANGULAR_SCENARIO, 5 ANGULAR_SCENARIO_ADAPTER, 6 'test/e2e/**/*.js' 7 ]; 8 9 autoWatch = false; 10 11 browsers = ['Chrome']; 12 13 singleRun = true; 14 15 proxies = { 16 '/': 'http://localhost:8000/' 17 }; 18 19 junitReporter = { 20 outputFile: 'test_out/e2e.xml', 21 suite: 'e2e' 22 }; 23

The complete documentation of the configuration file can be found in the Karma documentation. Lets look at this simple configuration file.

Line 1: This is to set the base path for all the file references. I always like to make the base path to the root of the project. In this case, the karma configuration file is sitting @ config folder under the root folder so we will change one directory to the root directory.

Line 3-7: specifies what are the files to use for running the tests, Line 3-5 are default values. Line 6 specifies where is the end to end test.

Line 9: This option specifies, if you want to continue watch the files for any changes. In our case it is ‘false’, which means, it will run only once and it will not continue watching for any changes.

Line 11: Which browsers will be used for end to end tests.

Line 13:  This one is critical. This option specifies, do you want to run the test only once or run once and run and wait for changes the run automatically. So to run the end to end test automatically in the background as you are developing is by setting this ‘false’ and also Line 9 and set the value to ‘true’.

Silverlight to Angular – 6 (Unit Testing)

Unit testing is one of the important and most often overlooked process in development. When we started development in Silverlight, we were so excited that with clear model, view and viewmodel separation, we were all set to create a fully tested code. Before you knew it, we created production code with Silverlight and shipped with 0% unit test. So the bottom line is, even if there are ways to create unit test, it is up to us to create unit tests. Well, creating unit tests is one thing and creating proper unit test is different thing. I remember creating unit tests, with reading data from database, calling bunch of methods to massage data before actually calling the method to test. I learned it hard way that, it was not right unit test. So there are two aspects of unit tests we need to remember, one is to write unit test and another is to write proper unit test. In this blog, lets look at the unit testing in Angular. Here is where I am going to break off from Silverlight and start to focus on Angular. One side note, because of the nature of Javascript when developing big application, do yourself a favor make sure, it have 100% coverage.

AngularJS has a decent but incomplete document on unit testing. Hopefully they will come around and finish it. We will look at straight forward unit testing with simple controller. If you have noticed so far, our controller is nothing but pure Javascript. It does not have any references to anything else like DOM manipulation or XFR calls. So our testing so far will be nothing but simple Javascript testing. It turned out there are ton of unit testing frameworks available for Javascript. As a Javascript beginner myself, I was looking for some testing framework which looked familiar and finally I settled on Jasmine. I made this decision purely on my previous RSpec experience. Once I get a handle on that, I will explore the other options available. If you would follow this link, it has fantastic one page reference to all the features available in Jasmine. It should not take more than an hour to go through and try them all out.

Lets see how can we create unit test for one of our sample code.

Problem: Given two numbers(integer or float, positive or negative), add them.

Approach: As a developer, I am still learning to approach this problem with TDD in mind. So to do TDD, you first write out the test cases your function need to handle before writing the actual code. So what are the possible test cases?

  1. It should add two valid integer numbers.
  2. It should add one integer and one float.
  3. it should add two float numbers.
  4. It should add when the numbers are zeros.
  5. It should add when one number is zero.
  6. It should add two negative numbers.
  7. It should add when one number is negative number.
  8. If first parameter is non numeric number, do not add.
  9. If second parameter is non numeric, do not add.
  10. If both the input are non numeric, do not add.

The proper TDD is only to write unit test based on the requirements. If you look at the (8-10), it was not mentioned in the requirement then why would we need to handle that situation? So don’t write those test cases.

So based on our requirement, I came up with 7 (skipped 3) test cases. Following TDD, write test first, make it fail and then write the code to pass. I came across two different approaches as well. One was to write the first test, make it fail and then write the code to make it pass and then go to your next test. The second approach was to write all the tests first and write the code to make them pass. I like earlier approach than later one. As I said before, I am going to use Jasmine and you can follow the install instructions in Jasmine to get Jasmine going and then follow along here; Here is the directory structure of my application

image

Under main web site, I have two folders, one for the app code and another folder for the testing. This way, we will not mix the production code with testing code and will not distribute the test code to production either. The test folder has spec folder, this is where all the unit tests housed. In the root of the test folder we have SpecRunner.html (we will see that in a minute), which when we run, will run all all the tests specified in the specrunner.

Iteration 1:

Unit Test:

First we are going to write our test code and we call it addition.spec.js; and the code looks like the following to accommodate our first test;

1 describe("Addition", function () { 2 3 var $scope, ctrl; 4 5 beforeEach(inject(function ($rootScope, $controller) { 6 $scope = $rootScope.$new(); 7 ctrl = $controller('additionCtrl', { 8 $scope: $scope 9 }); 10 })); 11 12 it("should add two integer numbers.", function () { 13 $scope.add(2, 3); 14 expect($scope.Result).toEqual(5); 15 }); 16 }); 17

Just to test 2 line of code we ended up writing close to 16 lines of code. This is because, we want to bring angular context and scope in to the testing as if it is running through angular. It is done with angular-mock.js, this will get added to specrunner.html in the next step. For now, lets look at the line (5-10). It is important to understand, how does the test run. When Jasmine runs, it will first look for any ‘beforeEach’ (line 5) and if found, in our case, there is one and it get executed before every test.  A test is nothing but the one starts with ‘it’, like at line (12).

Right now in our application, we are using default application and module and we are only creating a controller. As you know, in our controller code, we pass $scope from angular context to the controller. So to test our code, we need create mock context and that is what the controller have to use. To achieve this, before each test code, we will call inject method and for the giving rootScope, we create a mock Angular scope and that is passed to the controller in test as the scope. For now, you can use this as a template for writing our test and accessing the scope variable inside the test.

Lets look at the test itself, removing all the angular part out of it, which you will repeat in all your test suit once anyway. Without angular part in it, the test by itself will look like the following;

1 describe("Addition", function () { 2 it("should add two integer numbers.", function () { 3 $scope.add(2, 3); 4 expect($scope.Result).toEqual(5); 5 }); 6 });

So here is the rundown of this test;

  1. All the test starts with a test suite with ‘describe’ (line 1). Each test suite is given a suit name (Addition, in our case).
  2. If each test needs some common things to happen, like initializing, then call ‘beforeEach’ (line 5 in the previous complete test code).
  3. Every test, starts with ‘it’. ‘it’ has two parts (line 2), one is the name of the test and second one the test itself.
  4. In every test, after some action, validate the test result by ‘expect’ (line 4). ‘expect’ also has three parts, source, target and comparison operator. In our example, source is $scope.Result, target is ‘5’ and comparison operator is ‘toEqual’.

I would strongly recommend anyone interested in testing with Jasmine to read through their fantastic documentation with example.

Jasmine Spec Runner:

Now that the first test unit test code completed, lets add the information required to run the unit test in Jasmine. We run Specrunner.html to the tests we want to run.

1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 2 "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <title>Jasmine Spec Runner</title> 6 7 <link rel="shortcut icon" type="image/png" href="http://searls.github.com/jasmine-all/jasmine_favicon.png"> 8 <link rel="stylesheet" type="text/css" href="http://searls.github.com/jasmine-all//jasmine.css"> 9 <script type="text/javascript" src="http://searls.github.com/jasmine-all/jasmine-all-min.js"></script> 10 11 <script type="text/javascript" src="http://code.angularjs.org/1.0.6/angular.js"></script> 12 <script type="text/javascript" src="http://code.angularjs.org/1.0.6/angular-mocks.js"></script> 13 14 <!-- include source files here... --> 15 <script type="text/javascript" src="../App/Scripts/additionCtrl.js"></script> 16 17 <!-- include spec files here... --> 18 <script type="text/javascript" src="spec/addition.spec.js"></script> 19 </head> 20 21 <body> 22 </body> 23 </html> 24

Line (6 – 12) are all the required javascripts. Based on your application, you will add more library scripts here.

Line (15) specified which is the controller under test. This is pointing to the production code under ‘App’ folder.

Line (18) specifies, which are all the unit tests to run. In our case we have only one unit test spec to run.

App Setup:

You can run the test as it is now and it will fail with error like unable to find additionalCtrl etc., that is our red to green approach anyway.

Now that all the hooks are in place, open the windows explorer, find Specrunner.html and double click it. It will open a browser and run the test. This test will fail since we did not add any controller or view. So lets add them.

view:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="additionCtrl"> 8 First Number: <input ng-model="NumberOne"/><br/> 9 Second Number: <input ng-model="NumberTwo"/> 10 <button ng-click="add(NumberOne, NumberTwo)">Add</button><br/> 11 Result: {{Result}} 12 </div> 13 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 14 <script src="Scripts/additionCtrl.js"></script> 15 </body> 16 </html>

This is nothing more than vie, which we have seen before.

Controller:

Since we are following TDD, lets try make sure we stick to the minimum code to make the test pass.

1 function additionCtrl($scope) { 2 $scope.NumberOne = 0; 3 $scope.NumberTwo = 0; 4 $scope.Result = 0; 5 $scope.add = function (a, b) { 6 $scope.Result = parseInt(a) + parseInt(b); 7 }; 8 }

This code takes two objects and convert it to int and then add them. As you would expect nothing special and still javascript function. Now if you would run the test should run successfully.

Now that our first test is successful, lets write the second test.

Iteration 2:

It should add one integer and one float. Add the following code to the addition.spec.js

1 it("should add one integer and one float numbers.", function () { 2 $scope.add(2, 3.5); 3 expect($scope.Result).toEqual(5.5); 4 });

When this test is run, we would expect it to pass but it will fail since we are doing parseInt, which is converting the number to int thus losing the fraction part. So now the test is RED, go back to and fix the code to make it run. Instead of using parseInt, use Number function, which will retain the fraction.

Here is the modified controller

1 function additionCtrl($scope) { 2 $scope.NumberOne = 0; 3 $scope.NumberTwo = 0; 4 $scope.Result = 0; 5 $scope.add = function (a, b) { 6 $scope.Result = Number(a) + Number(b); 7 }; 8 }

Now if you run specrunner.html the test pass. You keep adding test and make sure all test pass.

While learning unit testing with Angular, I ran into bunch of problems, thanks to @karlgold for helping me sort things out.

NUnit vs MSTest

Couple of things I want to add on my observation on using MSTest vs NUnit. I always like to keep my deployment project and test project separate so that when I deploy my application there will be no test code sitting in production. By setting up a environment like this have a limitation when using NUnit. I might have some method private which if I want to test them using NUnit I can’t, since it can not find it. Only way I can test in NUnit is by exposing all the methods as public. On the other hand, with VS2010, I can right click on a private method and it creates test for me in the test project. So my class is clean and I am not exposing the helper methods as public. On this aspect, MSTest is awesome. This is a debatable . If you are creating API then you should be fine by exposing them public, but I do not like the idea to make methods public to support external tool. I like to keep the class clean. On the other hand,  MSTest lacks some of the simple fundamental assertion NUnit have, like collection assertion (without looking for separate method) and able to use TestCase to capture multiple test case against single test to keep the test DRY.

I am still using MSTest and NUnit in different project. MSTest along with Gallio really good, on the other hand, NUnit/NSpec/Growl is so cool as well. I hope MSTest will come up to speed on NUnit so that I can stay on MSTest.

Collection Assertion in MSTest and Kata

I have been doing Prime Factor Kata with one of my friend. If you want to follow along, there is a great video post at Rickard Nilsson blog. For this Kata, my first attempt was to use C# (obviously), NUnit. All worked very well. So out of curiosity, I decided to change it a little bit, use MSTest. I was expecting the same code I wrote in NUnit would work in MSTest but to my surprise, even my first test failed. Here is my first test

Assert.AreEqual(1.Primes(), new List<int>());

Here is the Primes implementation

public static List<int> Primes(this int n)
{
   return new List<int>();
}

Very simple. In NUnit, when you assert a condition on a collection, it just does assertion, while in MSTest, you can not use Assert against a collection.If you need to do assert against a collection, you need to use CollectionAssert.AreEqual. So when I changed the code to CollectionAssert, it worked like a charm. But here is a catch though, if I had the code like

public static IList<int> Primes(this int n)

The assertion will not work since IList does not implement ICollection, rather it implements ICollection<T>. There are ways to work around that, but I found a better way of doing the whole thing anyway. If you want to do it like NUnit, then, what I would recommend is to install NBehave. Specifically the NBehave for .Net. With that installed, now the same test I used in the beginning of the blog would be like this and more readable.

1.Primes().ShouldBeEqualTo(new List<int>());

Which is more readable and the same code works with NUnit and MSTest. The whole benefit of Kata for me besides the obvious, I was able to compare little bit of MSTest and NUnit. Based on what I have done, I decided to use NUnit just for ‘Parameterized Test Fixtures’. One of the thing we do while doing the Kata is code, refactor. It turned out, all my tests were copy paste except the input and expected result.So rather than have eight separate tests now I have one consolidated test with the input and expected result been passed in as attribute to NUnit. Here is the final code

[TestCase(1, new int[0])]
[TestCase(2, new int[1] {2})]
[TestCase(3, new int[1] {3})]
[TestCase(4, new int[2] { 2, 2 })]
[TestCase(6, new int[2] { 2, 3 })]
[TestCase(8, new int[3] { 2, 2, 2 })]
[TestCase(9, new int[2] { 3, 3 })]
[TestCase(3*5*7*11, new int[4] {3,5,7,11})]
public void Should_Find_Primes(int t1, int[] t2)
{            
     Assert.AreEqual(t1.Primes(), t2);
}

Thats all about it, good way to start a new year by learning something new and cool.