JavaScript Unit Test Abc_javascript Tips

Source: Internet
Author: User
Tags assert getdate
Objective
At present, unit testing is more and more valued by developers in software development, which can improve the efficiency of software development and guarantee the quality of development. In the past, unit testing is often seen in the development of the server, but as the division of the Web programming field gradually detailed, in the front-end JavaScript development field, can also carry out related unit testing, to ensure the quality of front-end development.
There are a variety of test frameworks in server-side unit tests, and there are some very good frameworks in JavaScript now, but in this article, we'll take a step-by-step implementation of a simple unit-testing framework.
JS Unit Test has many aspects, more is the method function check, browser compatibility check, this article mainly talk about the first kind.

This article examines the JS code is I previously wrote a JS date format method, the original here (JavaScript date format function, similar to the use of C #), the code is as follows:
Copy Code code as follows:

Date.prototype.tostring=function (format) {
var time={};
Time. Year=this.getfullyear ();
Time. Tyear= ("" +time). Year). substr (2);
Time. Month=this.getmonth () +1;
Time. Tmonth=time. Month<10? " 0 "+time. Month:time. Month;
Time. Day=this.getdate ();
Time. Tday=time. Day<10? " 0 "+time. Day:time. Day;
Time. Hour=this.gethours ();
Time. Thour=time. Hour<10? " 0 "+time. Hour:time. Hour;
Time.hour=time. Hour<13?time. Hour:time. Hour-12;
Time. Thour=time.hour<10? " 0 "+time.hour:time.hour;
Time. Minute=this.getminutes ();
Time. Tminute=time. Minute<10? " 0 "+time. Minute:time. Minute;
Time. Second=this.getseconds ();
Time. Tsecond=time. Second<10? " 0 "+time. Second:time. Second;
Time.millisecond=this.getmilliseconds ();
var onumber=time.millisecond/1000;
if (format!=undefined && format.replace (/\s/g, ""). Length>0) {
Format=format
. replace (/yyyy/ig,time. Year)
. replace (/yyy/ig,time. Year)
. replace (/yy/ig,time. Tyear)
. replace (/y/ig,time. Tyear)
. replace (/mm/g,time. Tmonth)
. replace (/m/g,time. Month)
. replace (/dd/ig,time. Tday)
. replace (/d/ig,time. Day)
. replace (/hh/g,time. Thour)
. replace (/h/g,time. Hour)
. replace (/hh/g,time. Thour)
. Replace (/h/g,time.hour)
. replace (/mm/g,time. Tminute)
. replace (/m/g,time. Minute)
. replace (/ss/ig,time. Tsecond)
. replace (/s/ig,time. Second)
. Replace (/fff/ig,time.millisecond)
. Replace (/ff/ig,onumber.tofixed (2) *100)
. Replace (/f/ig,onumber.tofixed (1) *10);
}
else{
Format=time. year+ "-" +time. month+ "-" +time. Day+ "" +time. hour+ ":" +time. Minute+ ":" +time. Second;
}
return format;
}

This code does not currently find a more serious bug, in order to test, we put. Replace (/mm/g,time. Tmonth) replaced by. Replace (/mm/g,time. Month), the error is that when the month is less than 10 o'clock, the month is not represented by a two-digit number.
Now there is such a word, good design is reconstructed, in this article is the same, we start from the simplest.
First edition: With the most original alert
As the first edition, we are lazy to check directly with alert, the complete code is as follows:
Copy Code code as follows:

<! DOCTYPE html>
<title>Demo</title>
<meta charset= "Utf-8"/>
<body>
<script type= "Text/javascript" >
Date.prototype.tostring=function (format) {
var time={};
Time. Year=this.getfullyear ();
Time. Tyear= ("" +time). Year). substr (2);
Time. Month=this.getmonth () +1;
Time. Tmonth=time. Month<10? " 0 "+time. Month:time. Month;
Time. Day=this.getdate ();
Time. Tday=time. Day<10? " 0 "+time. Day:time. Day;
Time. Hour=this.gethours ();
Time. Thour=time. Hour<10? " 0 "+time. Hour:time. Hour;
Time.hour=time. Hour<13?time. Hour:time. Hour-12;
Time. Thour=time.hour<10? " 0 "+time.hour:time.hour;
Time. Minute=this.getminutes ();
Time. Tminute=time. Minute<10? " 0 "+time. Minute:time. Minute;
Time. Second=this.getseconds ();
Time. Tsecond=time. Second<10? " 0 "+time. Second:time. Second;
Time.millisecond=this.getmilliseconds ();
var onumber=time.millisecond/1000;
if (format!=undefined && format.replace (/\s/g, ""). Length>0) {
Format=format
. replace (/yyyy/ig,time. Year)
. replace (/yyy/ig,time. Year)
. replace (/yy/ig,time. Tyear)
. replace (/y/ig,time. Tyear)
. replace (/mm/g,time. Month)
. replace (/m/g,time. Month)
. replace (/dd/ig,time. Tday)
. replace (/d/ig,time. Day)
. replace (/hh/g,time. Thour)
. replace (/h/g,time. Hour)
. replace (/hh/g,time. Thour)
. Replace (/h/g,time.hour)
. replace (/mm/g,time. Tminute)
. replace (/m/g,time. Minute)
. replace (/ss/ig,time. Tsecond)
. replace (/s/ig,time. Second)
. Replace (/fff/ig,time.millisecond)
. Replace (/ff/ig,onumber.tofixed (2) *100)
. Replace (/f/ig,onumber.tofixed (1) *10);
}
else{
Format=time. year+ "-" +time. month+ "-" +time. Day+ "" +time. hour+ ":" +time. Minute+ ":" +time. Second;
}
return format;
}
var date=new date (2012,3,9);
Alert (date.tostring ("yyyy"));
Alert (date.tostring ("MM"));
</script>
</body>

After the run will pop 2012 and 4, we know that the date.tostring ("MM") method is problematic.
This is a very inconvenient way, the biggest problem is that it only pops up the results and doesn't give you the right or wrong information, unless you're familiar with the code, it's hard to know that the result is wrong, and we're going to write an assertion (Assert) method to test it, clearly giving exactly what it is.
Second Edition: Check with assert
Assertion is an expression of the designer for the system should achieve a state of expectation, such as a method to add up to two numbers, for 3+2, we expect this method to return the result is 5, if you do return 5 then pass, otherwise give the wrong hint.
Assertions are at the core of unit testing, and the assertion function is provided in the framework of various unit tests, where we write a simple assertion (assert) method:
Copy Code code as follows:

function assert (Message,result) {
if (!result) {
throw new Error (message);
}
return true;
}

This method takes two parameters, the first is the message after the error, and the second is the assertion result
Test the code with assertions as follows:
Copy Code code as follows:

var date=new date (2012,3,9);
try{
ASSERT ("YYYY should return all year", Date.tostring ("yyyy") = = "2012");
}catch (e) {
Alert ("Test failed:" +e.message);
}
try{
ASSERT ("MM should return full month", date.tostring ("mm") = = = "04");
}
catch (e) {
Alert ("Test failed:" +e.message);
}

The following window will pop up after running:

Third Edition: Carry on the batch test

In the second edition, the Assert method can give clear results, but if you want to perform a series of tests, it is not convenient for each test to be caught unexpectedly. In addition, in the general test framework can give the number of success, the number of failures, and failure of the error message.

In order to be able to easily see the test results, here we put the results on the page with colored text, so here's a small output method Printmessage:
Copy Code code as follows:

function Printmessage (text,color) {
var div=document.createelement ("div");
Div.innerhtml=text;
Div.style.color=color;
Document.body.appendChild (DIV);
Delete Div;
}

Next, we'll write a testcase method similar to Jstestdriver, for batch testing:
Copy Code code as follows:

function TestCase (name,tests) {
var successcount=0;
var testcount=0;
for (var test in tests) {
testcount++;
try{
Tests[test] ();
Printmessage (test+ "Success", "#080");
successcount++;
}
catch (e) {
Printmessage (test+ "failed:" +e.message, "#800");
}
}
Printmessage ("Test Result:" +testcount+ "tests"), "+successcount+" success, "+ (Testcount-successcount) +" failures "," 800 ");
}

Test code:
Copy Code code as follows:

var date=new date (2012,3,9);
TestCase ("Date toString test", {
Yyyy:function () {
ASSERT ("YYYY should return", date.tostring ("yyyy") = = = "2012");
},
Mm:function () {
ASSERT ("MM should return", date.tostring ("mm") = = = "04");
},
Dd:function () {
ASSERT ("DD should return", date.tostring ("dd") = = "09");
}
});

The results are:

So we can see what went wrong at a glance. But is this perfect, we can see that the last Test in which var date=new date (2012,3,9) was defined outside the testcase, and the entire TestCase test code was used date, Here because the values of date are not modified in each method, so no problem, if the value of date is modified in a test method, the result of the test is inaccurate, so a setup and Teardown method is provided in many test frameworks to provide and destroy the test data uniformly, Here we add the setup and Teardown methods to our testcase.
Fourth edition: Unify the test data to provide the batch test

First we add the Setup and Teardown methods:
Copy Code code as follows:

TestCase ("Date toString", {
Setup:function () {
This.date=new date (2012,3,9);
},
Teardown:function () {
Delete this.date;
},
Yyyy:function () {
ASSERT ("YYYY should return", this.date.toString ("yyyy") = = = "2012");
},
Mm:function () {
ASSERT ("MM should return", this.date.toString ("mm") = = = "04");
},
Dd:function () {
ASSERT ("DD should return", this.date.toString ("dd") = = "09");
}
});

Since the setup and Teardown methods do not participate in the test, we will modify the TestCase code:
Copy Code code as follows:

function TestCase (name,tests) {
var successcount=0;
var testcount=0;
var hassetup=typeof tests.setup = = "function";
var hasteardown=typeof tests.teardown = = "function";
for (var test in tests) {
if (test=== "SetUp" | | test=== "Teardown") {
Continue
}
testcount++;
try{
if (Hassetup) {
Tests.setup ();
}
Tests[test] ();
Printmessage (test+ "Success", "#080");

if (Hasteardown) {
Tests.teardown ();
}

successcount++;
}
catch (e) {
Printmessage (test+ "failed:" +e.message, "#800");
}
}
Printmessage ("Test Result:" +testcount+ "tests"), "+successcount+" success, "+ (Testcount-successcount) +" failures "," 800 ");
}

The results of the run are the same as the third edition.
Summary and Reference articles

It said that good design is the result of continuous refactoring, the fourth edition of the above is not perfect, far from achieved, here is just an example. If you need this knowledge, I can later write the use of the various test frameworks.

This article is just JS unit test Entry Level example, let the beginner to JS Unit test has a preliminary concept, is a primer, welcome everyone to add bricks.

This article refers to the "test-driven JavaScript development" (personally feel good, recommended) The first chapter of the book, the test case is also a time function, but the writing is more complex, beginners are not easy to read.
Author: artwl
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.