Showing posts with label Unit Testing and TDD. Show all posts
Showing posts with label Unit Testing and TDD. Show all posts

Tuesday, June 3, 2014

JavaScript Dependency Injection.

Using JavaScript Dependency Injection for Spies, stubs and mocks in unit testing.

I was in the process of picking a Dependency Injector for use in a project in JavaScript. My default to narrow down the top three is to use Google as my initial search and then GitHub's star count as the top-three filter and then compare the features that I need.

After looking a SinonJS, sandboxed-module, rewire, and proxyquire I decided to be slightly more analytical and objective about how I compared them. I decided to include the Watch and Fork count in addition to the Star count. I created a spreadsheet that compared them:
 

watch star fork Avg
rewire 20 425 16 0.48
sinon 52 1471 233 2.08
sandboxed 10 190 24 0.29
proxyquire 2 195 12 0.15

84 2281 285 3

I averaged the modules giving each of the attributes a one third weighting. Given that starring is 27 times more common than watching you might question this weighting. I justify it because starring is a less costly action (no update emails) and more likely to do than watching.

Seeing this as a pie chart makes this information easier to absorb. The clear winner amongst these four modules is SinonJS with almost three-quarters of the attributes.







Wednesday, February 5, 2014

Roof Bug Fixing

Great blog post by Anna Shipman on Roof Bug Fixing.

She doesn't have comments enabled so I'll comment here.

I bought a newly built house in 2007 and after the buyer's inspection and the small fixes they did to it I was happy until the monsoons arrived and we had horizontal driving rain. This exposed leaks in the sealing around the windows.

I called the builders back in, explained what had happened and they fixed the leak and let me know it was done. I walked into the front yard and took the hosepipe and with a nozzle on the front of it sprayed the windows ten times harder than any monsoon could ever deliver water against them. This was my Black Friday load testing.

Of course it leaked and the repairers were standing inside my sitting room watching the water come through the seals around the window. The next day after it had dried they got back to work fixing it again. I was working upstairs and I could hear them spraying the window before they called me back to subsequently show me that it was fixed.

When someone comes around to fix something in my house my standard question before they start work is "how will you know that it's fixed?" and "how will you show me that it's fixed?" Sometimes this is moot and doesn't need to be answered.

Monday, July 8, 2013

TypeScript as a better JSLint

TypeScript, if you haven't heard of it, is Yet Another JavaScript Transpiler (YAJST). Their marketing pitch:
TypeScript is a language for application - scale JavaScript development. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open Source.
Apart from using the language for its added benefits you can also use the TypeScript Compiler (tsc.exe) as a very powerful and better form of JSLint that can catch "compile time errors" in a language that isn't compiled, in this case JavaScript.


A compiled language like Java, C, C++, or C# benefit from a first round of implicit unit tests which is the compilation of the code. i.e. before deploying the code it's been validated by the compiler and we know that syntactically it is "clean." Of course it may still be very buggy.

JavaScript doesn't have this benefit. We can run unit tests against the JS we write and if not syntactically correct we can catch some of those syntactic errors. However, if we don't have exhaustive, comprehensive and high quality unit tests we won't catch everything. We also can't test for intent.

Here's a trivial JavaScript example that works and is valid but may be a bug:

function getDivisor() {
    return "5";
}

function myTest() {
    console.log(10 / getDivisor());
}


If you run this through the TypeScript Compiler then you'll get this error:

TypeScriptTest.ts(3,17): error TS2112: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

JavaScript will execute this code correctly. It coerces the "5" in a string into an int and everything works as expected. However, TypeScript knows that the only type that can be returned by the getDivisor() function is string and by using implicit typing it knows that you can't (or shouldn't) try and divide by a string.

We can fix this by changing getDivisor() to look like this:

function getDivisor() {
    return parseInt("5");
}


Even if you don't use any of the features of TypeScript, your code quality can improve by inserting TypeScript as part of your build process. I'd suggest that you add this immediately after any other code in your system has been compiled and just before you run any unit tests.

As a note, TypeScript will not accept a .js file as an input, it will only accept .ts files. As such you will need to copy your .js files to a temporary location, renamed them to .ts files, run tsc.exe against them and capture the output.

Thursday, August 28, 2008

Unit Testing Saves the Day

I had a fantastic unit testing experience at work today. A couple of days ago I released a DLL to production that scans some text and transforms part of the text according to certain rules. An example of this would be the text that users enter into a forum post. Users would enter [b]some text[/b] and the text processor would transform that into <b>some text</b> before writing it out to a web page.

When writing the transform DLL I created several unit test that check every possibility that I could think of especially the edge cases. It was a great aid and tool to developing a robust and well tested DLL.

Inevitably as soon as it was release there an edge case came to light that I hadn't thought of and so I had to fix the "bug" in the DLL. Finding and fixing it was an absolute pleasure.

First off I took the block of text that demonstrated the bug and created a unit test that passed this block of text to the DLL and showed that the DLL was failing. At this point I haven't touched the errant transform code. I ran all the unit tests in the solution (takes about 5 seconds) and as expected they all passed the unit test except for the new one.

I then proceeded to fix the code and when done I reran all the unit tests again. This time the new test passed. This is called red/green testing. First you see the red light because it failed. You fix the code. Then you see the green light. I believe that Scott Hanselman says that it's called grey/grey testing if you're color blind.

This approach gave me an enormous amount of confidence to release the new DLL because I know that I haven't introduced any code that will break any of the previous standard and edge cases because I've tested them all again - and in only 5 seconds. Granted that it took me several hours to write all those tests but I would have probably spent at least 2 hours retesting this DLL after this fix had I not had the unit tests to do it for me.

I consider this a great victory for unit testing and test driven development and I am finally seeing my efforts in writing unit tests pay off in time saved and robust software.

Monday, June 2, 2008

Integration Unit Testing Analogy

I like Roy Osherove's restaurant analogy of Unit Testing vs. Integration Testing:

When it comes to paying for a meal...

Integration testing is like giving one big check to the group, with everyone having to calculate on their own how much they need to pay. sometimes everyone things they are good, but in the end the total amount may be too high or too low. There is a lot of interaction going on to decide who pays for what and who has already paid.

Saturday, May 3, 2008

Unit Testing Production Exceptions

I have a web site that gets a bit of traffic and I log exceptions on that site. Nothing exciting or special, a sort of Log4Net but home grown and speciliazed for the site. The log recently showed an index out of range exception. When I saw the exception I kicked myself for not having the foresight to also log all the options, parameters and data that the user had input so that I could reproduce the error. This got me thinking...

How about another or supplemental log that stored structured unit test data from the production environment? An exception happens in the production environment but it's an exception that's in a function that is directly unit tested in the development environment. During exception logging you write an XML fragment with all the relevant data to your log, supplemental log or DB.

When it comes to running unit tests you could have a setup script pull all unit test data from the production logs and insert it into the data store that's used for unit testing. You'd obviously have to do some checks to make sure that you don't have duplicate data as this is likely to happen if many users enter the same data that generates the same exception. Filtering this during the setup import would be the best place to cull the duplicates.

I've done a partial implementation of this. My log now has detailed input data and I currently copy/paste this into the unit test data store. Next step is to come up with a clever pattern to allow me to pull data for different types of unit tests. To be continued...