Click here to Skip to main content
12,501,406 members (50,925 online)
Click here to Skip to main content
Add your own
alternative version

Stats

6.7K views
46 downloads
6 bookmarked
Posted

Testing Public and Private Functions in JavaScript using Jasmine and Chutzpah

, 31 Mar 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
JavaScript Testing

Introduction

There is a big debate among the online community about how to test private functions in a module when we have only access to public functions from it. This article explains about JavaScript testing using module pattern approach. It is useful if you want to test private functions.

Using the Code

Basically, this article has three sections, HTML, JavaScript and testing.

HTML

HTML has simple controls that take two inputs and four buttons that calculate simple calculations such as Add, Subtract, Multiple and Divide.

User can enter desired numeric inputs and user can click on desired buttons to get the calculated output.

@{
    ViewBag.Title = "Home Page";
}
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/publicmodule.js"></script>
<script src="~/Scripts/privatemodule.js"></script>
<h2>Index</h2>


<span id="firstNumberSpan" hidden="true">First Number:</span>
<input type="text" id="firstNumber" hidden="true"/>
<br/>
<span id="secondNumberSpan" hidden="true">Second Number:</span>
<input type="text" id="secondNumber" hidden="true"/>
<br/>
<input id="addBtn" type="button" title="Add" 
value="Add" hidden="true" class="click"/>
<input id="substractBtn" type="button" title="Substract" 
value="Substract" hidden="true" class="click"/>
<input id="multiplyBtn" type="button" title="Multiply" 
value="Multiply" hidden="true" class="click"/>
<input id="divideBtn" type="button" title="Divide" 
value="Divide" hidden="true" class="click"/>

<br/>
Result:
<label id="result">0</label>

<script type="text/javascript">
    publicModule.Init();
</script> 

JavaScript

JavaScript contains two modules:

  1. Public module, which will interact with HTML for all the display logic sides
  2. Private module, which will contain all the logic for calculations, which will return only the required output

By having private module, we can write tests using jasmine and see what they are returning. By this, we know that they will be returns. Here, we will write all the happy path and sad path tests so that it does not break.

In public module, it will manage all the UI related logic and we can write test to check the behavior of the browser.

Public Module
var publicModule = (function ($) {
    //Public function
    var init = function() {
        $("#firstNumber").show();
        $("#firstNumberSpan").show();
        $("#secondNumber").show();
        $("#secondNumberSpan").show();
        $("#addBtn").show();
        $("#substractBtn").show();
        $("#multiplyBtn").show();
        $("#divideBtn").show();
        attachEvents();
    };

    var attachEvents = function () {
        $(".click").click(function () {
            var firstNumber = $("#firstNumber").val();
            var secondNumber = $("#secondNumber").val();
            var result = privateModule.Calculate(this.id, parseInt(firstNumber), parseInt(secondNumber)); //Private function
            $("#result").html(result);
        });
    };

    var api = {
        Init: init, //Public function
    };
    return api;

}(jQuery));
Private Module
/*
All functions in private module will be public
*/
var privateModule = (function ($) {
    var add1 = function (first, second) {
        return first + second;
    };

    var substract1 = function (first, second) {
        return  first - second;
    };

    var multiple1 = function (first, second) {
        return first * second;
    };
    
    var divide1 = function (first, second) {
        return first / second;
    };

    var calculate = function(control, first, second) {
        var result = 0;
        switch (control) {
        case "addBtn":
            result = add1(first, second);
            break;
        case "substractBtn":
            result = substract1(first, second);
            break;
        case "multiplyBtn":
            result = multiple1(first, second);
            break;
        case "divideBtn":
            result = divide1(first, second);
            break;
        default:
        }
        return result;
    };

    var api = {
        Add: add1,
        Substract: substract1,
        Multiply: multiple1,
        Divide: divide1,
        Calculate: calculate
    };
    return api;

}(jQuery));

Testing

I used Jasmine and chutzpah for testing this modules.

Public Module Testing
/// <reference path="Scripts/jquery-1.8.2.js" />
/// <reference path="Scripts/jasmine.js" />
/// <reference path="Scripts/publicmodule.js" />
/// <reference path="Scripts/privatemodule.js" />

describe("public tests:", function () {
        var pathViews = 'Views/Home/Index.cshtml';
    
        function getMarkup(path) {
            var sResult = null;
            $.ajax({
                type: "GET",
                async: false,
                url: path,
                dataType: "text",
                success: function (result, s, x) {
                    sResult = result;
                },
                error: function (result) {
                    console.log("getMarkup failed to load");
                }
            });
            return sResult;
        }
    
        var htmlMarkup = getMarkup(pathViews);

    it("1 load page", function() {
        $("body").html(htmlMarkup);
        publicModule.Init();
    });

    it("2 should be 3 on adding 1 and 2", function () {
        $("#firstNumber").val(1);
        $("#secondNumber").val(2);
        $("#addBtn").click();
        var result = $("#result").html();
        expect(result).toEqual('3');
    });
    
    it("3 should be -1 on substract 1 and 2", function () {
        $("#substractBtn").click();
        var result = $("#result").html();
        expect(result).toEqual('-1');
    });

    it("4 should be 2 on multiply 1 and 2", function () {
        $("#multiplyBtn").click();
        var result = $("#result").html();
        expect(result).toEqual('2');
    });
    
    it("5 should be 2 on divide 1 and 2", function () {
        $("#divideBtn").click();
        var result = $("#result").html();
        expect(result).toEqual('0.5');
    });
}); 
Private Module Testing
/// <reference path="Scripts/jquery-1.8.2.js" />
/// <reference path="Scripts/jasmine.js" />
/// <reference path="Scripts/publicmodule.js" />
/// <reference path="Scripts/privatemodule.js" />


describe("private tests:", function () {

    it("1 should be 3 on adding 1 and 2", function () {
        var result = privateModule.Add(1, 2);
        expect(result).toEqual(3);
    });
    
    it("2 should be 6 on adding 2 and 4", function () {
        var result = privateModule.Add(2, 4);
        expect(result).toEqual(6);
    });
    
    it("3 should be 3 on substract 6 and 3", function () {
        var result = privateModule.Substract(6, 3);
        expect(result).toEqual(3);
    });

    it("4 should be 2 on substract 6 and 4", function () {
        var result = privateModule.Substract(6, 4);
        expect(result).toEqual(2);
    });
    
    it("5 should be 18 on multiply 6 and 3", function () {
        var result = privateModule. Multiply(6, 3);
        expect(result).toEqual(18);
    });

    it("6 should be 24 on multiply 6 and 4", function () {
        var result = privateModule.Multiply(6, 4);
        expect(result).toEqual(24);
    });
    
    it("7 should be 2 on divide 6 and 3", function () {
        var result = privateModule.Divide(6, 3);
        expect(result).toEqual(2);
    });

    it("8 should be 1.5 on multiply 6 and 4", function () {
        var result = privateModule.Divide(6, 4);
        expect(result).toEqual(1.5);
    });

    it("9 should be 3 on calculate function with 1 and 2 for addBtn control", function () {
        var result = privateModule.Calculate("addBtn",1,2);
        expect(result).toEqual(3);
    });
    
    it("10 should be -1 on calculate function with 1 and 2 for substractBtn control", function () {
        var result = privateModule.Calculate("substractBtn", 1, 2);
        expect(result).toEqual(-1);
    });
    
    it("11 should be 2 on calculate function with 1 and 2 for multiplyBtn control", function () {
        var result = privateModule.Calculate("multiplyBtn", 1, 2);
        expect(result).toEqual(2);
    });
    
    it("12 should be 0.5 on calculate function with 1 and 2 for divideBtn control", function () {
        var result = privateModule.Calculate("divideBtn", 1, 2);
        expect(result).toEqual(0.5);
    });
  
}); 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Divikiran
Software Developer (Senior)
Australia Australia
I am a, hands-on, Microsoft C# Analyst Programmer using Xamarin, Azure, WPF and MVC as my preferred tools, also as Team Lead and Scrum Master. My experience include in analysis, object oriented design, development and implementation of client, server, web and windows based applications and enterprise mobile apps using latest Microsoft technologies such as MVC, WPF and Xamarin Forms.

I have worked with Microsoft technologies for over 10 years building software for various private sector companies, applying both technical knowledge and managerial expertise.

My preferred technology stack includes C#, Azure, WPF, MVC, Entity Framework, Xamarin and SQL Server and highly prefer working on various design patterns and architectures.

An integral part of my work is to provide my clients with a high standard of understandable technical documentation: I have written few articles listed few page down in this resume, designs, as well as User Guides.

Using Azure for over 1.5 year, migrating application to the cloud, fully managed continuous integration for all environments.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160919.1 | Last Updated 1 Apr 2014
Article Copyright 2014 by Divikiran
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid