Thursday, July 24, 2008

Automated Tests in my life - part 6

What is Mocking?

Sometimes we want to test a method, which is dependent on other methods
results or some complecated data. In these situations in order to write a little unit test, we need to make lots of initializations.
For example if we take a code:

public string GetProcessedBatchOfCAMLCommands()
{
string batch = string.Empty;

// initialize the new instance of SP Site
using (SPSite site = new SPSite("http://localhost"))
{
using (SPWeb web = site.OpenWeb())
{
SPListItemCollection UnprocessedSPListItemsCollection = GetListAndQueryItems(web);
string listGuid = web.Lists["Processed Documents"].ID.ToString();
batch = GetFormattedCAMLBatchCommand(UnprocessedSPListItemsCollection,listGuid);
string batchReturn = web.ProcessBatchData(batch);
}
}
return batch;
}

Lets look at the GetFormattedCAMLBatchCommand method. Let's say we want to test it.
The method is dependent on SPSite, SPWeb and etc... There is chain of dependencies.
So how can we test GetFormattedCAMLBatchCommand without involving these dependencies?
We should isolate the method from other dependencies.
Ok, so we can mock other dependencies and send to GetFormattedCAMLBatchCommand "faked" objects. We will be able to unit test it.
This is a principle, I will try to explain you this by simple example

Tuesday, July 22, 2008

Automated Tests in my life - part 5

Relieve a stress

A question... Is it familiar situation when you wrote a quality code according to
the requirements and then you were told that you did not understand the requirements?
Bad feeling, a? I made a good job and now am wrong!!!
As I figured out it happens to many people and happens a lot...

A real story from my own practice.
Once upon a time I had to write some logic for a table (logic was separated from UI –this helps to test UI logic automatically without viewing on screens all the time). The colors and numbers in table change, according to some logic. The behavior of the table was a requirement from customer. So I had to write some code for the logic in order to answer on the customer requirements.

First of all the tests that answer the questions were written – functions that can return specific values (I used TDD technique). After each test the code "for" the
test was implemented. When all finished and I ran all the tests that covered all scenario, all tests were green (passed), task was finished, tested integrated with GUI, the task was done.

Two month later… Customer side said there is a bug in color changing logic. They expected different behavior in some cases. Of course my boss asked me a simple question - why did it happened?

I really did not remember all the code I wrote couple of months before and all the logic behind it, but after finding the tests that covered this specific logic, with great self confidence I showed how they pass to bosses. Nothing broke, nothing changed!!!
It means that all the tests answered on requirements and all the code was written
exactly according to requirements. When bosses saw tests and green lights, indicating tests pass, they were happy. It was clear that code was ok, according to logic from customers. What was the reason of all this?

Customers changed the requirements a little bit; at the beginning they did not have a clear picture of all, so problem was not at our side. As you can see, I had my own advocate and for free.

Thursday, July 17, 2008

Automated Unit Tests in my life - Part 4


Test Driven Development and Automated Tests advantages


Later I tried to figure out what can be improved by coding in a “new style”.
So these are some of my conclusions:
1) When you develop with tests first, you are building a base for your code:
First you add tests, then add code – so all of the code I added was minimum code, required.
That’s how we create “clean” code.
2) Then you add new test for additional functionality and write code in order to pass the tests
3) Since that foundation is always in place, it lets you modify or re-factor the implementation that built on top without having to worry about breaking some piece of functionality.
4) Let’s say I wrote tests that checks my class various situations. So if I forgot what the code does or someone new joins the team, it is easy to read through a fixture for any class and immediately know how that class will behave in various situations.
5) If I forget if a method is supposed to throw or return false or etc…, a quick scan of unit tests will provide the answer.
6) Since the tests are part of my workflow, they’re always kept up-to-date. And … the system gives you self confidence.

Automated Unit Tests in my Life - Part 3

Part 3. Work or play?


The World before

Let’s think about our working cycle. I am not sure about you but… here how my working style looked before:

1) Wrote the code, which is a solution for requirements

2) Wrote a tester (Exe, or GUI)

3) Checked that it works. Mostly I checked expectations visually: using debugger or printing the results to a file (Text or XML) and looking at the file.

Let’s see which problems could appeared:

You write code to solute some requirement. Then you check it. Sometimes you have to write more code, which breaks your old test, so you write a new test. This is the reason that you will want first to finish writing all the code and then to write tests at the end. And I will tell you from experience - this is bad, really bad! Coding like this is problematic: the code becomes bombastic - it will take you more thinking and time to write it, you should remember many details, if you went out in the middle, takes long time to remember all the details, and this is the reason we write some not needed, I call it not "clean" code.

2) Tests run took a long time because I had to look at each test result visually and it took lot of time (sometimes had to look at big files). Of course we don’t want to run “old” tests when new are added.

3) Mostly sometimes we forget to write all tests, especially when the code is done after tests are written. Even if we write tests, we not always run all of them because it takes long time – to run each test and look visually at all tests results.

There are also situations when unit tests were not made. In order to save time people made integration tests, or in better case “unit tests” that check number of dependent components together. It never ends well, I can tell.
When you work test driven it’s all different… What is different ?


Work is a game

After few weeks of using automated unit tests and test driven, I made my “own” system of writing a code.
And the work became to look like a game. Here are the rules of the game:

1) Write down requirements logic – all detailed requirements (on paper or document)

· Try to write a question for each requirement in the code – this will be the name of your test function.

· Run current test. Of course the test will fail – sure there is no code yet.

· Now write a minimal code in order to pass the test.

· Run current test and make it pass (by adding required code and etc). Test passes when expected result equals to test result.

· Write the different expectations for current function, so copy – paste same code, just change input and expected result values. Think when your specific test can fail. So each requirement will have different test for different situation

Now add new function (or logic) test. Each time when you add a new test – run all tests. This will show you that if you have added some new logic you did not break old one. Sometimes when we add a new logic we break old one. When new requirements are implemented, logic is changed, so expected result is affected and an assertion Assert.AreEqual(actual, expected); fails.

After practicing this I found in internet a nice diagram that shows similar flow.
They call it Test Driven Development. And here is a TDD (Test Driven Development) cycle:


I hope we are agreed that this is a big change in coding cycle. A different way of thinking and different way of writing the code. It is not so easy to change the way of thinking when we are used to other things. And it was not as easy for me at the beginning.

But in our life we always learn something new, change things, our tastes change.
We become better, our code quality becomes higher – I call it self-development or evolution.

Automated Unit Tests in my life - Part 7

TDD & Time

Sometimes I hear people sayin that TDD developement takes more time thatn without using TDD...
You know - it is true. Wrting code with tests takes more time then writing code
without tests.
But you can be sure that in long term you safe a lot of time...

When you run whole tests together you have No more repeat bugs.
When you run all the tests automatically - Full regression test of your system takes minimal time.
You spend the significant majority of your time developing new functionality rather than debugging existing code.
Debugging time is reduced by at least a factor of 10.
When a little logic is added, it is easy to find non-actual or broken logic by running whole set of tests

So as we can see - we save a lot of time by using Automated tests...
Bosses are suprised, how fast

Wednesday, May 14, 2008

Software: Automated Unit Tests in my life

Part 1. How did it begin?
Before writing about automated unit tests technical details, I will write you about my experience with the automated unit tests… A little bit about my programmer history:
After graduating University in 1997 (Applied Mathematics), life took me to work as algorithms and software developer in some complicated big project with lots of mathematical calculations and logical stuff, where I earned lots of programmer skills. The project was one those, where all the developers had to make lots of tests (the situation where quality was more important than time). All the team tested all code by writing unit tests and integration tests. This is why the quality of my code was good. At the time I did not know anything about automated unit tests. All the tests were written manually…

So when the automatic unit tests came into my life? All began with my work in some software medical company. After about a year of my work in the company my boss suggested me to “try” write unit tests automatically, using “Nunit” and more then that – write tests before code (test driven development).
I was shocked and disappointed… First of my thoughts were:
”Why me? Is my code not good enough? I have a good testing experience with my working and testing style. Why should I change the way of working? More than that - why should I write the tests before code? And changes now - when I have so much work?” It felt like some entering to my privacy – way of programming, way of life, thinks I was used to… But as you can understand- I agreed, because am writing this one. After few hours of practicing I still did not understand why automated unit test and test driven it so good? In the next part you will see why first experience began to change my opinion…

Part 2. First experienceA day later I began to like it… And you know why?
Here are the first things I liked about automated unit tests and test driven:
First of all – I realized that writing tests and code using automated unit tests did not take more time then my “regular” way of working at that time. Now before writing a new function (method) in class I write test that calls that function. I have to think about how client will call my function, about possible arguments and possible returned values – this saves time.
1) Why else does it save time?
a) I do not have to write “*.exe” tester after my function was finished.
b) I do not have to look at test results visually, I can see at once if test is passed (green colors)
Automated means – you write expectations and results and expected results are compared automatically. This is a part of an assertion code
Assert.AreEqual(actual, expected);
If expected is equal to actual, the test is passed (green), if not – test is failed (red light). Assert is done automatically in runtime and you do not have to look at the test result visually.
c) It is easier and quicker to write a test that uses files (text or XML)
d) I did not have to write same initialization or tear down code to number of tests, because Test Initialize and Test Tear Down is called automatically with each test for test project (file).
2) Automated – helped me to find bugs in my code and produce better quality code in the short time
a) Once after testing my function and adding more code – some private function that is used by number of publics, I ran 2 tests automatically and figured out that have “broken” one of tests by adding code.
So I had to go back and fix code. I realized now that I can come quicker to a higher quality code.

Software Experience: Automated Unit Tests in my life

Introduction

This is an article of a software developer, who decided to share some knowledge and experience in automated unit tests. I think this one can help in everyday work of people like us.
This is not a pure technical article. It is a real story and comes to help producing better quality code. I will try to give some nice tips and show black and white sides of my automated unit tests experience.
About the name of an article ... You might ask: Hey, man – isn’t it too much? You could name it “Unit Tests in my code, work, or etc – but “in my life”? You will find the answer on that question by reading this material, which consists of several parts. And here they are:
· How did it begin – how, when and why did I begin using automated unit tests
· My first experience – Good, bad, why do I need it
· The New style of work. How could Programming be like playing a game.
· Programming without automated unit tests and Test Driven Development - differences
· Programming without automated unit tests and Test Driven Development - differences
· Self confidence in your work
· Automated unit test weakness and how to prevent them
· How can we mock without affecting the code