Browser testing is different from unit testing of js code. The latter is generally the logic testing of code functions before release, and there are already many mature solutions in this regard,
Advantages of automated testing:
Reduce repetitive work. Let the machine automatically help us complete the required interactive operations and verify our page functions.
Automatic monitoring. By automatically returning to our page function, you can provide an alarm when the function fails and provide a reference for manual troubleshooting.
Phantomjs can be understood as an unbounded browser, which can drive the browsing behavior of its page through pipeline code, while the latter is some encapsulation of the former in the ease of use API.
Here we will demonstrate how to use casperjs to capture Baidu homepage
For the installation of these two things, it is very easy to read the official documentation. I will not repeat them here.
First create a js file baidu. js:
Var casper = require ('Casper '). create ();
Casper. start ();
Casper. thenOpen ('http: // www.baidu.com/', function (){
Casper.captureSelector('baidu.png ', 'html ');
});
Casper. run ();
The above code mainly involves three things:
Create a casperjs instance require ('Casper '). create (), which can be understood as a browser process
Open a page, such as casper. thenOpen (...);
Screenshot page image casper. captureSelector
Run
Casperjs baidu. js
Check the image results generated by this script.
Wait! Why is the image only X in size?
The reason is that I created a browser process to load the page, but did not specify which browser to load. Therefore, when creating a casper instance, you can specify the window size of the browser, or even impersonate the browser of the mobile phone by specifying the userAgent. For example, you can specify safari as iPhone 5 and set the window size:
Var casper = require ('Casper '). create ({
PageSettings :{
// Impersonate a browser
UserAgent: 'mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) version/7.0 Mobile/11A465 Safari/9537.53'
},
// Browser window size
ViewportSize :{
Width: 320,
Height: 568
}
});
After we run it again, is it like this?
Simple application
In the preceding example, you can see how to use an unbounded browser to load a page and get a screenshot of the page.
We can know what the page looks like without opening a browser. So every time we run this casperjs script, we can see whether our page is normal through screenshots.
However, judging by the naked eye is definitely against the original intention of "automation", so we must use tools to help us analyze.
The simplest and most intuitive method is "pixel comparison", that is, compare two or multiple screenshots to each pixel or a certain range of regions one by one, in this way, the differences between images can be produced, as shown in the figure below:
In actual application, you can specify an image as the reference graph. If the screenshot is different, an error occurs on the online page.
The Pixel comparison tool is quite mature. Here is a very close solution to front-end development: Resemble. js.
Why is it close to the front end because it uses canvas. We know that each pixel of an image can be determined by RBGA (red, blue, green, alpha) values:
The main principle of Resemble. js is to draw the image to be compared to the canvas and read the image data of the pixel (or area) to be compared to determine the image difference.
To better integrate with phantomjs and casperjs, the author of Resemble. js also developed The Resemble. js-based encapsulation of phanw.ss.
Phanw.ss uses simple APIs for image comparison:
Phanw.ss. screenshot ("# CSS. selector1", screenshotName1 );
Phanw.ss. screenshot ("# CSS. selector2", screenshotName2 );
Phanw.ss. compareFiles (screenshotName1, screenshotName2 );
If the image to be compared is inconsistent, a comparison chart is generated, and the differences are marked with conspicuous colors, similar to the following:
Note:
The page screenshot comparison is inconsistent, and it does not prove that our page has an exception, such as an advertisement space. These areas with frequent changes may be different in each comparison, therefore, it is not appropriate to compare advertising spaces or other frequently changing positions. In practical applications, it is not recommended to compare screenshots on the entire page. This method is too simple and crude. We should conduct subdivision and comparison of each area of the page for fine-grained monitoring.
Cookie
Since it is a browser test, no cookie is involved, and casperjs does not encapsulate cookie operations, you can use phantomjs to directly "type" cookies:
Phantom. addCookie ({
Name: 'cookies ',
Value: 'value ',
Domain: '.xx.com ',
Path :'/',
Secure: false,
Httponly: false,
Expires: Date. now () + (1000*60*60*24*5)
});
In the previous appetizers, the pages we visited were not logged on. Here, we can manually implant the cookie value of the logon status of the Baidu account to achieve login access.
Open Baidu homepage in PC-side chrome, log on with your account, and copy the key cookie BDUSS value of Baidu account in developer tools
And hard code to your casperjs script:
Phantom. addCookie ({
Name: 'bduss ',
Value: 'Cookie value you copied ',
Domain: '.baidu.com ',
Path :'/',
Secure: false,
Httponly: false,
Expires: Date. now () + (1000*60*60*24*5)
});
The complete code is run here. Let's look at the result again.
Done! The user name already exists in the upper right corner, indicating that we have logged on!
Interaction
Simple screenshots and comparisons are far from meeting our testing requirements. For automation principles, implementing automated page interaction is king. Don't worry.
The previous section describes how to manually implant cookies for logon. The following describes how to implement the logon process of Baidu on the mobile phone.
First, preview the entire script login. js code. The following describes the entire process:
Create an instance. The configuration is basically the same as that in the appetizer. For the sake of speed, the instantiated configuration selects not to load the image.
2. Load the page
3. Capture the non-logon page:
Casper.captureSelector('1.png ', 'html ');
In this step, image 1.png is displayed, and there is no user name in the upper right corner (not logged on): unlogined
4. Read and output all current cookies
Var cookies = phantom. cookies;
For (var I = 0, len = cookies. length; I <len; I ++ ){
Console. log (cookies [I]. name + ':' + cookies [I]. value );
}
This step outputs the result to the command line: we can see that the current cookie does not have the key cookie BDUSS of the Baidu account.
5. Click "log on".
Casper. mouse. click ('# login ');
Casperjs (phantomjs) supports a wide range of mouse events that support complex interactions:
Click
Doubleclick
Rightclick
Down
Up
Move
Allows you to specify the CSS3 path of an operation target.
6. Click "log on" to go to a logon page with the username and password entered. For convenience, please wait 3 seconds until the logon page is loaded.
Casper. wait (3000 );
7. Capture the logon page
Casper.captureSelector('2.png ', 'html ');
8. Fill in the form
Casper. evaluate (function (){
Document. querySelector ('[name = username]'). value = '***';
Document. querySelector ('[name = password]'). value = '***';
});
Evaluate is a very useful method.
9. Intercept the login form
10. Click log on.
11. Waiting to jump back to the home page
12. The homepage page after logon is intercepted.
13. Read the cookies one by one and display them in the command line
Finally, run the test script casperjs login. js to get four screenshots, respectively recording the interaction effect of the key steps in the entire logon interaction process:
Not logged on
Logon page
Enter information
Logon successful
The difference between Figure 1 and Figure 4 is that the user name in the upper-right corner of Figure 4:
At the same time, the BDUSS cookie value after logon is also read in the command line:
Let's try again.
Actions in iframe
Phantomjs (casperjs) not only operates on the current page, but also switches the current context to iframe for operations, which makes the page test embedded in iframe much easier.
Operation Area
Phantomjs (casperjs) supports the use of CSS3 selector and XPath to operate on the target to be operated (click, screenshot, etc.), and can also be operated by specifying the region boundary, for example, you can specify x/y coordinates/width/height to click or take a screenshot:
Casper.capture('capture.png ',{
X: 200,
Y: 300,
Width: 200,
Height: 300
});
Limitations of interaction
In the real world web, some interactive functions are not mechanical operations. Sometimes, due to security or other factors, some page restrictions are imposed, requiring our interaction to be dynamically output according to some situations, this function is difficult to fully automate. For example, the above Baidu login function sometimes has a verification code:
At this time, it is very difficult to use machines to help us log on. Therefore, I will introduce how to manually implant cookies to achieve login.
Unit test
Through the previous introduction, phantomjs (casperjs) has been able to implement many automated functions. On this basis, it is very easy to implement unit testing.
Casperjs provides a relatively complete unit test API
In unit testing, each testsuite is packaged in a closure:
Casper. test. begin ('your testsuite ', 0, function (test ){
// Unit test code
});
For example, the following is a set of test cases to test whether the title and log location of the Baidu page are correct:
Casper. test. begin ('test demo', 0, function (test ){
Casper. start ();
Casper. thenOpen ('http: // www.baidu.com/', function (){
// Test whether the page title is correct
Casper. test. assertTitle ('Baidu review ', 'Page title ');
// Test the location information of the logo
// Obtain x/y/width/height
Var layout = casper. getElementBounds ('# logo ');
Layout = JSON. stringify (layout );
// Verify the compliance
Casper. test. assertEquals (layout, '{"height": 87, "left": 0, "top": 53, "width": 320 }', 'logo \'s boundary ');
});
Casper. run (function (){
Casper. test. done ();
});
});
Complete Code test. js is here
Run casperjs test. js
You can see the following output in the command line:
Both cases have passed!
Compared with the visual display of the preceding screenshots, unit testing provides us with more concise test results.
In addition, the test module of casperjs can also generate XML results after testing. For example, the results of the above example are as follows:
<? Xml version = "1.0" encoding = "UTF-8"?>
& Lt; testsuites time = "2.228" & gt;
<Testsuite name = "test demo" tests = "2" failures = "0" errors = "0" time = "2.228"
Timestamp = "2015-08-31T13: 30: 12.462Z" package = "test">
<Testcase name = "page title" classname = "test" time = "2.223">
</Testcase>
<Testcase name = "logo's boundary" classname = "test" time = "0.005">
</Testcase>
<System-out>
</System-out>
</Testsuite>
</Testsuites>
The XML results can be combined with alarm and other systems to implement various powerful automation functions.
Problem
Browser compatibility. After all, phantomjs (casperjs) provides an unbounded webkit kernel browser, so it cannot cover ie. Currently, the Gecko kernel's UI-free browser already has a solution called SlimerJS and supports the same APIs as phantomjs.
Device compatibility. In the case of a variety of mobile phones and other terminal devices, it is more difficult for the server to simulate all the hardware and software environments without an interface browser.
Phantomjs + Casperjs makes page capturing and interaction in the background very simple
Casperjs is based on Phantomjs, while Phantom JS is a WebKit for JavaScript APIs on the server side.
This is a combination of my thoughts on finding a background that comes with a browser kernel ". Therefore, when I found this thing, I began to get excited by myself. After some research, it was a pity that the background connection to websites and page interaction suddenly became very simple. Especially for webpage operations that require logon.
Therefore, I used it to write two small examples for some website login and clicking some links and buttons on the Internet. During the compilation process, let's just say, "we don't have to worry about Cookie any more if you want to know where to do it ~" Feeling ~
After reading this example, do comrades unconsciously think of some words, such as "sign-in" and "Daily logon?
Var casper = require ('Casper '). create ({
Verbose: true,
LogLevel: 'debug ',
PageSettings :{
LoadImages: false,
LoadPlugins: true,
UserAgent: 'mozilla/5.0 (Windows NT 6.1; rv: 17.0) Gecko/20100101 Firefox/123456'
}
});
// Phantom. outputEncoding = "gbk ";
Casper. options. viewportSize = {width: 1680, height: 924 };
Casper. start ('http: // bulo.hujiang.com/app/login? Source = nbulo & returnurl =/home /');
Casper. waitForSelector ("form # myform input [name = 'txtusername']",
Function success (){
This. test. assertExists ("form input [name = 'txtusername']");
This. fill ("form ",{
'Txtusername': 'shixiaobao17 ',
'Txtpassword': '××××your password *****'
}, False );
This. click ("input # btnLogin ");
},
Function fail (){
This. test. assertExists ("form input [name = 'txtusername']");
});
Casper. waitFor (function check (){
Return this. getCurrentUrl (). indexOf ("bulo.hujiang.com/home")>-1;
}, Function then (){
Console. log ("logon successful !!!!!!!!!!!! ");
}). Then (function (){
Console. log ("perform other operations after logon !!!!!!!!!!!! ");
If (this. exists ("# btn_card_do ")){
This. click ("# btn_card_do ");
This. waitForSelector ("# my_hb_btn", function success (){
Console. log ("logging successful! ");
}, Function fail (){
Console. log ("logging failed! ");
});
} Else {
Console. log ("You have been stuck today! ");
}
});
Casper. run (function () {this. test. renderResults (true );});