Test Driven Development by Example

Tweet about this on TwitterShare on LinkedIn0Share on Google+2Share on Reddit1Buffer this pageFlattr the authorEmail this to someonePrint this page

Test Driven Development by Example

In an earlier post, we have seen how to setup a framework/workspace that can be helpful to write easily testable Javascript code. Now we will dive into writing some code with the TDD approach. So lets get started.

Table of Contents

T.D.D. – Test Driven Development

Part 1 : Understand what TDD is all about. I ran into this amazing video by Rebecca Murphy. Where she explains as how Testable javascript needs to be written

A few excerpts from her presentation

  • There will be bugs in any code
  • Unit tests  – “Given this input do I get that output”
  • This will force you to write code such that you end up with code that is safely refactorable
  • Such an approach will clearly set an expectations as what other people can expect from your code
  • Testing events like “click”, “focus” is not your job unless you are writing a wrapper for it.
  • Splitting the code into 4 major parts (e.g.: Searching for something & submitting)
    • Presentation & Integration (UI layer, buttons, text boxes etc)
    • Application State (clicking submit button again & again, understand that a search on a certain text is already going on and not redo the same..)
    • Data/Server Communication (Any form of data communication – Server, cookie, local storage)
    • Setup (Event handlers that connect the above 3 pieces)
  • Guiding Principles for testable code
    • Use constructors to create instances
    • Support configurability
    • Keep Methods simple
    • Don’t intermingle responsibilities
    • And… Write test first!! So you have to write code that will pass the tests!

Now we have fair understanding as what is expected when some one says Testable Code

In short

tdd

source

 Part 2 : Take up a requirement and develop a calculator application with TDD

Requirements

  1. We need to build a responsive static web page that will display a simplified calculator as show in the images below, and is responsive.
  2. When the user types in a valid number in field 1 and then a valid number in field 2, the appropriate action should take place (ex: add).
  3. All the operations needs to run on user’s key up/text box blur event.
  4. All the code that is written in the application should be 100% testable and refactorable.
  5. A code coverage report needs to show the coverage % to be 100

Desktop View

calculator_desktop

Tablet View

calculator_tablet

Mobile View

calculator_mobileSo assuming that you have done the setup from here, we will start off with the development.

Step 1: Lets make the required UI changes. We will use  grunt watch for this. We have already changed the Top nav bar background color and the page background. Now lets make the link color as black. Back to variables.less and search for  @navbar-inverse-link-color and then replace @gray-light  with  #222

Step 2: Lets add the markup in such a way that the layout is responsive. Following bootstrap grid layout, we end up with a markup like this.

Replace the contents of div with class content-main  in app/index.html  with the below markup

 Refresh the app/index.html  and you should see the new layout. Re-size the browser and validate the responsive nature.  

Step 3: Lets theme the calculator. Back to gitbash to make sure grunt watch  is running. Then open  variables.less. Now, search for  @well-bg  and replace its value with  #52888a . And badges  @badge-color  to  #000  and  @badge-bg  to  #fff

Wait for grunt to build the less files, and back to the page, refresh. Bam!!! Our required UI.

All the variables.less  changes

Step 4: Our business logic. This is a very critical juncture, where we make all our design decisions on how we write the testable javascript code.

So here is what we are going to do. Lets write down what needs to happen

Case Field I value Field II value  Result
I valid valid valid
II valid invalid invalid
III invalid valid invalid
IV invalid invalid invalid

So now we have a clear picture on the outcome of our function. Now, we need to pass in the values on key up of each field.

So there we are clear, we will write 2 pieces of code, part 1 our business logic that will take in 2 numbers and return a value, part 2 the handler that will call this function. So what are we waiting for, lets write some test cases!!

Lets navigate to test/spec  folder are create a new file called  Calculator-Spec.js. Open it in your favorite editor.  We are going to write test cases using Jasmine. This is a pretty extended tutorial by Evan Hahn on how you can leverage Jasmine. For this tutorial, we might not go that deep.

So, in your Calculator-Spec.js, lets add a couple of test cases. To keep things a more hands on-ish, I will be testing & developing the code only for the addition. You can go ahead and implement the remaining.

To keep things a bit interesting, lets assume that there is no validation to the input field. We end up with a few test cases as below.

Test Cases & Expected Results

Case Field I Field II Expected results
Correct Sum 5 6 11
Incorrect Sum 5 6 9
Negative SUM – I -5 -6 9
Negative value + Positive value -5 6 1
Sum is Zero -6 -6 0
Invalid Field 1 – I dummyText 6 0
Invalid Field 1 – II undefined 6 0
Invalid Field 1 – III null 6 0
Invalid Field 1 – IV $$ 6 0
Invalid Field 2 – I 5 dummyText 0
Invalid Field 2 – II 5 undefined 0
Invalid Field 2 – III 5 null 0
Invalid Field 2 – IV 5 $$ 0
Both Invalid Fields I dummyText dummyText
Both Invalid Fields II null null 0
Both Invalid Fields III null undefined 0
Both Invalid Fields IV $$ #@ 0


Back to Calculator-Spec.js 
, lets add test cases

Then grunt, Ctrl + c  in case you are in watch mode. Then lets run grunt jasmine:dev. You should see the output as below

add_fail

Yay!! Our cases failed! Look at those ravishing red messages. This is test driven development all about.

We now know what is expected of the add function. So lets gets started with out source development.

Navigate to app/scripts  and create a new file called Calculator.js , And lets write a basic Calculator add function. We will create a Calculator object that will hold all our functions.


Save the file and now back to grunt and run  grunt jasmine:dev. The output would be like this

add_pass_1

What!!!.. A few cases passed and a few failed. But, but my logic is correct! Well.. my friend, this is where test driven development makes its presence felt.

So lets analyse what went wrong, did you notice “dummyText6″ in the above output? what happened? Javascript appended both the values as string! Here is a good discussion on javascript strings. And did you notice the NaN? Yes, our undefined & null are NaNs.

So lets clean that up. we will add a validation check on our add method. Lets write a helper method, that will validate the numeric issue and parse the text as well. (Note: Ideally we need to write test cases for this method too and then utilize it).

So here is our helper method, lets add it at the end of the Calculator.js  (for now, later on we can move to a helper file). Explanation of the below code here.

Now our Calculator.js  will look like this

Now back to grunt lets run  grunt jasmine:dev

Bam!! our output!

add_pass_2

 Looks like everyone is happy!! Good to see a lot of greens doesn’t it?

Now our business logic is ready, lets hook up the logic with the handler. Back to app/script/main.js , lets add a handler.

In app/index.html, lets add a reference to Calculator.js  above main.js , by adding the below line above main.js  include

<script src="scripts/Calculator.js"></script>

Refresh app/index.html  and start typing things into Field I & Field II. You should see expected output as per our Test Cases & Expected Results table. Neat right?

Lets run some code coverage and see what is the %. Back to  gitbash , lets run  grunt jasmine:coverage. You will see an error  ReferenceError: Can't find variable: $. Ignore that for now and you can go to tddBootstrapBoilerPlate\coverage\html and launch index.html . This will show that our code coverage is not 100%. Because of our Javascript event handler, that is delegating the keyup event to the add() .

So now you can see how effective and simple it is to develop a 100% testable javascript code. The entire code base is uploaded here with the steps done till now. Github repo.


Thanks for reading! Do comment.
@arvindr21

Tweet about this on TwitterShare on LinkedIn0Share on Google+2Share on Reddit1Buffer this pageFlattr the authorEmail this to someonePrint this page