DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. JavaScript
  4. Baby Steps to Backbone.js: Unit Testing of Models

Baby Steps to Backbone.js: Unit Testing of Models

Alexander Beletsky user avatar by
Alexander Beletsky
·
Dec. 03, 12 · Interview
Like (0)
Save
Tweet
Share
5.61K Views

Join the DZone community and get the full member experience.

Join For Free

Unit testing is important part of development process. If you care about the application state and code quality, sooner or later you start to automate the tests. My experience shows, sooner is better option. There are several approaches to unit testing, `test-first` and `test-after`. There are many holy wars appears on that topic. I would say, both options works - but `test-first` or test driven development, works better for me.

By the end of the day, it's only important that tests exists and helping to catch regression bugs. Still, developing by `test-first` helps to see the problem before ahead and in general provides better code quality (that would conclude the holy war).

Today we going to write some tests, that would cover our existing model class Feedback.js. Since the code is already written, we will go `test-after` approach. Fortunately, the code is quite simple, so it would not make a problem to unit test that. But before, let's setup our testing infrastructure.

Folders and files

We'll have a new folder called `spec`. Inside the spec folder, I'll have `models` and `views` folders that would contain tests for models and views.


Tests runner

I'll be using Jasmine test framework. It's very easy to setup it, what we need is jasmine.js and jasmine.css to be placed on proper folders and setup a test page. Test page is a simple html file, which will be entry point for our testing. If you download jasmine standalone bundle you will see SpecRunner.html inside. It could be easily tailored for custom needs. In the head part of tests.html we need to reference all required .css and .js files.

<title>Feedback form specs</title>
 
<link rel="stylesheet" type="text/css" href="content/jasmine.css">
 
<script type="text/javascript" src="/scripts/libs/jquery-1.7.2.js"></script>
<script type="text/javascript" src="/scripts/libs/underscore.js"></script>
<script type="text/javascript" src="/scripts/libs/backbone.js"></script>
<script type="text/javascript" src="/scripts/libs/jasmine.js"></script>
<script type="text/javascript" src="/scripts/libs/jasmine-html.js"></script>
<script type="text/javascript" src="/scripts/libs/mock-ajax.js"></script>
 
<!-- Sources -->
<script type="text/javascript" src="/scripts/src/models/Feedback.js"></script>
 
<!-- Specs -->
<script type="text/javascript" src="/scripts/spec/models/Feedback.spec.js"></script>

Jasmine tests in essence

Testing with Jasmine is fun and easy. Jasmine is BDD-style framework, so if you practiced TDD with another frameworks, the style might confuse initially. Let's review the Jasmine test skeleton.
describe('Jasmine spec', function () {
    var value;
 
    beforeEach(function () {
        value = 1;
    });
 
    it ('should fail', function () {
        expect(value).toBe(0);
    });
 
    describe('when value is changed', function () {
        beforeEach(function () {
            value = 0;
        });
 
        it ('should pass', function () {
            expect(value).toBe(0);
        })
    });
});

In this example, value is our SUT (System under test). beforeEach() function is `context-establish` function, where SUT is initialized (in TDD it's both arrange/act). it function is assert part. Here, we set our expectations about which state should SUT be in to. Notice, that beforeEach are nested into describe, so you tweek SUT depending on case.

Writing some tests

The only one functionality that Feedback.js model contains currently is validation. Let's test that.
describe('Feedback.js spec', function () {
    var model;
 
    beforeEach(function () {
        model = new Feedback();
    });
 
    describe('when model is validating', function () {
        var errors;
    });
});
This is something to start with. It does not do any asserts, so now we'll add some real cases. First case, is than both `email` and `feedback` attributes are absent.
describe('when email and feedback fields are absent', function () {
    beforeEach(function () {
        errors = model.validate({});
    });
 
    it ('should have 2 errors', function () {
        expect(errors.length).toBe(2);
    });
 
    it ('should have email fields as invalid', function () {
        expect(errors[0].name).toBe('email');
    });
 
    it ('should have feedback field as invalid', function () {
        expect(errors[1].name).toBe('feedback');
    });
});
It's is possible that user put email, but forgot about feedback.
describe('when email is set, but feedback is absent', function () {
    beforeEach(function () {
        errors = model.validate({ email: 'a@a.com'});
    });
 
    it ('should have 1 error', function () {
        expect(errors.length).toBe(1);
    });
 
    it ('should have feedback field as invalid', function () {
        expect(errors[0].name).toBe('feedback');
    });
 
    it ('should have error message', function () {
        expect(errors[0].message).toBeDefined();
    });
});
Moving on, user might put feedback but forgot about email.
describe('when feedback is set, but email is absent', function () {
    beforeEach(function () {
        errors = model.validate({ feedback: 'TDD is awesome'});
    });
 
    it ('should have 1 error', function () {
        expect(errors.length).toBe(1);
    });
 
    it ('should have email field as invalid', function () {
        expect(errors[0].name).toBe('email');
    });
 
    it ('should have error message', function () {
        expect(errors[0].message).toBeDefined();
    });
});

Tests report

If you now try to run test.html in browser, you will something like that.


Conclusions

Testing of Backbone.Model's is pretty simple thing. It's nothing more than testing some business logic, that might reside inside. Testing of views is a bit trickier thing, but we will see how to do that next time.


unit test Backbone.js

Published at DZone with permission of Alexander Beletsky, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • AWS Cloud Migration: Best Practices and Pitfalls to Avoid
  • How to Secure Your CI/CD Pipeline
  • Real-Time Stream Processing With Hazelcast and StreamNative
  • Top Three Docker Alternatives To Consider

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: