Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Tuesday, 12 February 2013

One gun, many enemies

I spent some time, re-investigating Javascript. After few months of intensive TDD and SOLID training I was curious how those principles apply in slightly different environment. Guess what, they do not differ that much... I wanted to write about all this little later, after gathering some experience from battle ahead. However, Watirmelon post, invited me to attack this subject immediately.

I got through available testing frameworks for Javascript and decided on Jasmine. Why? Mainly because its syntax - BDD style which is fashionable this season. Second reason is that it has really cool documentation. Finally, basic set up was painless to me.


Let's look at basics - what I expect from different types of tests and how Jasmine fits into those requirements:

1. Unit Testing

Aims
  1. Shoot them one by one
    (structure your code so that it is easier to maintain)
  2. Be sure you kill with every shot
    (verify small bits of code to nail down bug issue)
  3. Kill them all
    (verify edge cases)
  4. Kill them quick
    (provide fast feedback on issues)
Choose gun which is
  1. Fast shooting - the faster you shoot, the more enemies you will kill
    (unit tests must be blazing fast)
  2. Reliable - your gun is stuck and you are dead
    (when unit tests are brittle you will stop depending on them)
  3. Always close
    (unit tests are your gun, so you must be able to run them all locally)

Jasmine works great for all those aims, as it is really fast and it allows you to stub both objects and DOM elements. Keep in mind that Unit Testing is useful only if you either write new code or refactor old one. Do not ever try to write UT for a ready code which you don't intend to refactor. It's like shooting dead. You simply cannot kill them with another bullet.

2. Integration Testing

Aims
  1. Beware of the hidden sniper
    (test against external dependencies like files, databases, network services)
  2. You are part of your squad
    (verify that components of the application work well together)
Choose the right strategy
  1. Observe the environment
    (try to use depenedencies as close to real problem as possible e.g. static file, database with test data, test version of a service)
  2. Point in the right direction
    (do not try to test your stack top-down, instead concentrate on interfaces and adapters that you could not test in unit tests)
Integration tests will naturally be harder to quickly setup, they might broke due to configuration problems or inaccessible external services. That's why you don't want to have that many of them. Still, you want to know that all your problems are due to your partner changing protocol. Once again nothing stops us from using Jasmine here.

3. Acceptance Testing

Aims
  1. Confirm you are fighting the right war
    (show specification to your product owner/manager/client)
  2. Keep clean supply routes
    (test the functionality of your up with full set up and all dependencies)
  3. Find hidden mines
    (test your application in all environments you deploy your application to)
Tips
  1. Speak in their language
    (use tool which allows writing tests in natural language e.g. Cucumber or SpecFlow)
  2. Take your time
    (those tests will be slower, so accept that you will not always run them locally)
  3. Spend your resources wisely
    (acceptance tests are naturally much more brittle then other types of tests, so try to keep their number reasonably small)
This is where I would not recommend Jasmine, simply because it doesn't fit this job. It's syntax is based on programming language, so it is harder to read by non engineers. Jasmine allows you to execute events and call your code. However, your users will be most likely using a browser to interact with your code, so it is much better to use some tool that also uses browser to test web page.


Conclusion

I find Jasmine extremely well suited for unit and integration testing. I wouldn't use it for acceptance tests as there are quite few better tools for that job.

Post Scriptum (on DOM dependency)

On his blog Alister Scott also complains about integration issue between his server-side code and client-side code. His experience is that changes to ids and classes in mvc application result in not working javascript. The issue is serious and shows one important mistake which is hardcoding dependencies. Ids and class names are configurable details and Javascript code should be agnostic of them. To illustrtate let's look at test case for a very simple code from my pet-project:

    
describe("GameController", function(){
  describe("During Initialize", function() {
    var view;
    var subject;

    beforeEach(function() {    
        setFixtures("<div id="myid"></div>");
        subject = new GameView();

        subject.CreateFabricInDiv("#myid");
    });

    it("creates fabric in div", function(){
        expect($("#myid")).not.toBeEmpty();
    });

    it("holds pointer to canvas", function(){
        expect(subject._canvas).not.toBe(undefined);
    });
}); 
 

Do you see how "#myid" parameter is passed into method call? We moved configuration detail out from Javascript code. In my opinion it is simplest solution to Alister problem. This will enable keeping ids/classes consistent between code which generates them and Javascript that uses them. It also helps with code re-usability as you can use the same code on two separate pages with differing ids!

Friday, 25 January 2013

Training Camp

The time has come, I need to change something and I already know what it is. I want to join the best of the best. I want to be at the forefront of development. I want to deliver best quality software. I want to deliver it fast. I want to see that light int the eyes of people when I present them what I do. I want to have fun every day. I want to be agile.

They are also saying that they pay well...

And they train you while you are fighting for them.

And there is time for innovation. Great! Let's go for it!

The only problem is that joining the best of the best requires Me to be the best. But I am not. Actually, I am pretty good. When I shoot code, it usually brings value. The only thing is that it just explodes afterwards... And all this talk about TDD and SOLID, it seems a little bit overrated, isn't it?

This were many things that constantly banged my mind before I made first step - I wrote down CV. Then I literally sent it to every offer in the internet that had a 'agile' keyword inside. I tried banging on the doors of the most popular companies and I responded to vague offers from agencies. I decided not to be picky as long as I could join a real world agile company. Oh, yeah and I thought the best city in Europe for such a task will be London. Not that far from home, but far enough to make me feel I am changing my life.

After countless emails and few phone calls I got my first serious offer. The head hunter arranged phone interview due to distance between me and the company.

Phone interview? No problem. It's just talking about stuff. Right?
Just before the phone call my heart was pounding and I crossed my room like 1000 times there and back again. And it used to be quite big room!

The first part of the interview was a little like a cultural interview. I was asked about the book I read recently (and mentioned in cover letter - The Agile Samurai: How Agile Masters Deliver Great Software). I was asked about my values, and why I wanted to work in the agile environment. It was all pretty obvious and easy. I really wanted to work in the agile company. But then technical questions came. And I thought that I know something about development:

- Do you know what the acronym SRP stands for?
- Not really.
- Then do you know what is single responsibility principle?
- I guess it's that each class in a program should be responsible for one thing only? -
Yeah I was not that sure
- Do you know what is dependency inversion?
- It is when you do no want to bind classes to each other, so you use external library to do that. -
If you are not aware I didn't seen difference between DI and IOC at this time
- Do you know what Open-Closed principle means?
- Not really.
- Do you know why the 'var' keyword was introduced
- As a syntactic sugar, so that you do not need to write full class name when it is obvious.
- Not exactly...


And it went like this... At the end the voice said: "Thank you do you have any questions for us?". And I did had questions about their agile practices, about continous improvement and so. The heck, I want to get from this call as much as I can about real world agile. After all this talk I felt sad and devasted. I went to the backyard and started to cut wood into pieces.

For some hard to understand reason they still wanted me to come to the face to face interview. YEAH!

I got to do also a programming exercise. It was about writing discount logic for an internet shop. I did my best. I took free time from work and I spent day and night before deadline doing everything by TDD, trying to structure code the best I could. I was pretty proud of the outcome. I had full suite of unit tests, quite extensive set of integration tests and all requirements of the task were written down as the acceptance tests. I learned unit testing library well and used it for all tests types. I had no time to learn IOC library, so I did all injections by hand in constructors. I overcame few automation obstacles which arouse from using only free tools in .NET environment. And it refreshed my git skills. After all I want to best, right? The code was sent. And once again I had time to sleep.

But not for a long...

Head hunter actually saw that my chances are rising after company viewed the code, so he set up another interview for the same day. This other company also had as part of their interview code test done before hand. This time it was building console interpreter of robot moves. I had the experience but, the time was short. I had skipped one night sleeping (just before filght to London) and once again I did my best. I sent half finished code (but with Unit, Integration and Acceptance tests) just 2 hours before my flight departures. I downloaded all information about SOLID code and Object Oriented design I could and I hoped for the best! Just before I got to the airport the head hunter called me saying he made an appointment for yet one more interview. Chances of getting into agile were high! And all I learned on the way was already to my benefit.

After all I could also be agile. And I could do TDD. And I had acceptance tests. I can join the best of the best.