Skip to content

Instantly share code, notes, and snippets.

@grant-roy
Last active August 29, 2015 14:07
Show Gist options
  • Save grant-roy/6b498d4f2474a0336741 to your computer and use it in GitHub Desktop.
Save grant-roy/6b498d4f2474a0336741 to your computer and use it in GitHub Desktop.
Javascript Testing Part 1

####Javascript Testing Part-1

####Why do we test code...in an automated fashion.

Mark Ethan Trostler ( Google )..from Testable Javascript :

You have to write unit tests, so quit messing around and write some.

From the angular docs ( Many people at Google ):

JavaScript is a dynamically typed language which comes with great power of expression, but it also comes with almost no help from the compiler. For this reason we feel very strongly that any code written in JavaScript needs to come with a strong set of tests. We have built many features into Angular which makes testing your Angular applications easy. So there is no excuse for not testing.

####So the key to writing great, maintainable code... : we must test...and we must test in a particular fashion.

####Different types of tests:

  • Unit Tests (Isolate a small piece of functionality and test only that)
  • Regression Tests (Ensure no bug creep with new features, guard against known bugs appearing in the future)
  • Integration Tests (End to End Test)

####Unit tests

Unit tests concern themselves with testing the smallest unit of meaninguful functionality...in isolation. We also have the notion of 'code coverage' or the number of lines of code exercised by a test suite.

What we want to do is test a small piece of code that does one conceptual thing:

function add (a,b) {
   return a + b
}

####What makes a good unit test?

Good Test = Code coverage + Test Edge and Non Edge Cases of parameters + Mocked Dependencies( Isolation )

Code coverage alone is not good enough when unit testing...we must work the possible values of the parameters to ensure the functionality we expect.

####Some possible pseudocode to test the sum function

  • Set two variables, a = b = 2
  • Set a variable named result = 0
  • Call sum function and assign the return value to result
  • Check that 'result === 4'

####Can we guarantee that the sum function works?

  • We didn't check that passing two strings in would add the strings correctly.
  • A string and a number??....null or NaN??
  • Is the function specified for only numbers? ( This points to the value of good documentation )

####Isolation

Load only the bare miniumum required for a test

In general you will probably be testing at the individual method level...provided your methods are well designed and exercise the Single Responsibility principle.

Isolation is the concept by where we are introduced to the idea of 'Mocks' or 'Stubs'. Essentially the goal is to isolate the code under test by 'mocking out'..or 'stubbing' other parts of the code it depends on.

####Scope

Scope must be small. Examine the smallest piece of functionality that makes sense..in isolation. Only the method is being examined...and all dependencies are mocked out.

Our goal is to have a large number of unit tests...each with a small scope.

####Another look at sum

We can't test our function well unless we know exactly what to test for...and in that respect..a fully commented function is a beautiful thing (And people reading the code will think that a pro, and not an amateur wrote it). Lets take a look:

/* 
* This function adds two numbers, otherwise return null
* 
* @param a first Number to add 
* @param b second Number to add 
* @return the numerical sum or null
*/ 
function sum (a,b) {
   return a  + b
 }

Does the code live up to the comments?

####Writing tests before code...or...'TDD'

The school of thought here is basically this...writing tests has been proven to increase software quality...and the number of tests written is positively coorelated with quality. So we need tests..but developers are lazy..so what do we do?

In this case we advocate writing tests before you write any 'working' code. What does this do?

You first write a test that fails, this test will examine a piece of functionality that does not exist. By writing the test first, the tesst then serve as a Specification. This is a bonus.

The most important effect of writing the test first though is that.... The tests are ensured to get written!!. This is a critical point...by far most important thing is that we actually end up with working tests.

####Positive Testing

Positive testing is ensuring that what you expect will happen does...meaning the 'common path' or how you most expect the method to be called.

it(" Adds By Param! ", function() { 
    var a= b= 2;
    var expected = 4; 
   
    expect( sum(a,b) ). toEqual( expected ); 
    
})

####Negative Testing

Can the code handle values that it's not expecting? This is where we beat up the code and think of ways to break it. Here we want to stress test the parameters for values we might not expect in normal use.

it(" Adds By Param! ", function() { 
    var a=2;
    var b;  //Note b is undefined here
    
    var expected = null; 
   
    expect( sum(a,b) ). toEqual( expected ); 
    
})
@meidlin
Copy link

meidlin commented Oct 16, 2014

Bravo Grant, bravo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment