自动化e2e测试 -- WebDriverJS,Jasmine和Protractor
发布在Node.js测试研究2014年4月22日view:14995
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

enter image description here

自动化e2e测试 – WebDriverJS,Jasmine和Protractor

e2e或者端到端(end-to-end)或者UI测试是一种测试方法,它用来测试一个应用从头到尾的流程是否和设计时候所想的一样。简而言之,它从一个用户的角度出发,认为整个系统都是一个黑箱,只有UI会暴露给用户。

想象一下,如果把这些自动化的测试工作换成人工来做,那会多么的令人头疼,尤其是对于那些具有大量交互的应用,手工测试将会以编程不可能的任务。

在本文中,我们将会介绍如何使用webdriverJS和Jasmine来进行自动e2e测试。

什么是WebDriverJS?

和WebDriver相关联的东西很多,以至于很多初学者会感到比较困惑。

因此,在本文中我们从头讲起。

Selenium

正如Selenium网站中提到的:

Selenium将会自动操作你的浏览器。

仅此而已。

Selenium已经支持了大部分主流的浏览器,它是一个用于自动化测试的绝佳工具。因此无论你在测试你的应用时做了些什么,比如导航到一个页面,点击了一个按钮,在一个输入框中写了一些文字,提交了一个表单等等,Selenium都可以替你自动完成这些事。

WebDriver

WebDriver(或者Selenium 2)基本上指的都是特定浏览器控制代码的语言绑定和实现。

WebDriver引入了一个JSON wire protocol用于将不同的语言和浏览器控制器进行交流。

例如,在浏览器中点击了一个元素,绑定将会发送一个POST请求到session/:sessionId/element/:id/click

因此,WebDriver的一端是一个语言绑定,而另一端,是叫做Selenium server的服务器。二者之间的交流使用的就是JSON wire protocol。

WebDriverJS

正如前面所提到的,WebDriver拥有很多不同的语言绑定,像是Ruby,Python等等。JavaScript是web世界的主要语言,也载入了WebDriver的列表中。于是我们迎来了WebDriverJS!

你可能已经猜到了,WebDriverJS就是一个简单的对于JSON wire protocol的包装,它同时暴露除了高等级的函数接口来使我们的生活更加轻松。

现在如果你搜搜webdriverJS,你可能会看到两个不同的绑定,它们的名字分别是Selenium-webdriver和webdriverjs(确实有很多driver),两个绑定都是node模块。你可以使用任何一个你喜欢的,但是我们依然会坚持使用官方的版本 – selenium-webdriver。

假设你现在有一个JavaScript项目需要进行自动化的e2e测试。首先你需要安装这个模块:

npm install selenium-webdriver  

好了!你现在可以require这个包,然后进行一些小小的配置以便你能够在浏览器中打开任何网页:

var webdriver = require('selenuim-webdriver');

var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

driver.get('http://www.baidu.com');

为了运行你的测试代码,你可以这样做:

node testfile.js  

注意:除了npm包之外,你还需要下载你想要使用的WebDriver实现。对于2.34.0版本,Selenium-WebDriver原生的支持ChromeDriver。你可以简单的下载ChromeDriver的副本并确保它能够在你的PATH中找到。其他的driver(比如. Firefox,Internet Explorer,以及Safari),仍然需要标准的Selenium server。

和其他语言绑定的不容之处

WebDriverJS和其他的语言绑定之间有一个重要的区别 – 它是异步的。

因此如果你在python下写下面的代码:

//伪代码  
driver.get(page1);
driver.click(E1);

由于Python(以及其他语言)的API都是同步的,因此所有的带啊吗语句都是同步执行的。但是在JavaScript中却不是这样的情形。为了确保一些行为的前后顺序,WebDriverJS使用了Promise。简单来说,一个promise就是一个能够在它完成之后执行一些代码的对象。

但是到这里还没有结束。即使是有了Promise,上面的代码也会变成下面的样子:

//伪代码  

driver.get(page1).then(function(){
  driver.click(E1); 
});

你在这里有没有闻到一丝丝回调地狱的味道?为了让代码更加整洁,WebDriverJS对Promise进行了一些包装,于是便有了ControlFlow。

简单来说,ControlFlow从下面几个方面阻止了回调地狱:

  • 它保留了一个行动的列表
  • WebDriverJS暴露的函数并没有做实际的事情,它们只是把需求的任务push到上面的列表中
  • ControlFlow将每一个then的新入口放到了列表的最后,因此确保了它们之间的顺序

总而言之,它允许我们编写下面的代码:

//伪代码 driver.get(page1); //隐式的添加到上面行为的then()中
driver.click(E1);

是不是碉堡了!

ControlFlow也提供了一个excute函数来将你的自定义函数push到执行列表中人后返回这个函数在特定执行环境下解析/拒绝之后的返回值。因此你可以使用promise并且在你的自定义代码中做任何异步的事情:

var flow = webdriver.promise.controlFlow();

flow.execute(function () {
    var d = webdriver.promise.defer();
    do_anything_async().then(function (val) {
        d.fulfill(val);
    })
    return d.promise;
});

将WebDriverJS和Jasmine结合起来

我们可以使用Selenium进行浏览器自动化测试。现在我们需要一个测试框架来处理我们的测试。这时我们需要Jasmine。

你可以通过npm来安装Jasmine:

npm install jasmine-node  

如果我们要让前面的testfile.js代码来检查页面的标题是否正确,代码将会如下所示:

var webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

describe('basic test',function(){
    it('should be on correct page',function(){
        driver.get('http://www.baidu.com');
        driver.getTitle().then(function(title){
            expect(title).toBe('Baidu');
        });
    });
});

现在上面的文件需要使用Jasmine-node命令来运行,如下所示:

jasmine-node testfile.js  

上面的操作会让浏览器做上面所提到的事情,但是你会注意到Jasmine什么结果都没给出。为什么?

这是因为Jasmine完成了执行步骤同时没有任何的expect语句被执行,因为期望被放在了getTitle函数的异步毁掉中。

为了解决异步的问题,Jasmine-node提供了一种方法来告诉特定的it块:它是异步的。只需要在it的回调中添加一个done,并在最后执行即可。于是我们可以把上面的嗲吗改成下面的形式:

var webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

describe('basic test',function(done){
    it('should be on correct page',function(){
        driver.get('http://www.baidu.com');
        driver.getTitle().then(function(title){
            expect(title).toBe('Baidu');
            //Jasmine-node会一直等到这个异步函数执行完毕再调用done()函数来进入下一个测试单元
            done();
        });
    });
});

小提示:你可能需要改变Jasmine用于测试的时间:

jasmine.getEnv().defaultTimeoutInterval = 10000; //以微秒为单位

Angular应用的额外福利

AngularJS框架从一开始就是非常倾向于测试的。不用说,这些应用汇应该花费很多时间在e2e之上。

Protractor是一个又AngularJS团队编写的库,它是一个队WebDriverJS的包装,同时Jasmine在这里被指定用来测试,真是太爽了。

我们来看看Protractor都有什么额外的福利:

  1. 不需要基于id,css选择器,xpath等查询元素,你可以基于绑定,模型,迭代器等等进行测试。太贴心了!
  2. 其中的Jasmine可以接受promises。因此,我们可以用下面的代码进行上面的测试来检查标题:

    driver.getTitle().then(function(title){ expect(title).toBe('Baidu'); });

可以重构为:

expect(driver.getTitle()).then('Baidu');

除此之外,AngularJS中海油很多非常酷的特性来进行end-to-end测试。

总结

e2e对于现在的应用来说非常重要,因此它对于自动化测试来说也变得很重要。你可以选择很多工具来帮助你进行自动化测试。

希望本文能够帮助你开启你的e2e之路。还在等什么呢?赶快做一些end-to-end测试吧!


本文译自e2e-testing-with-webdriverjs-jasmine/,原文地址http://engineering.wingify.com/posts/e2e-testing-with-webdriverjs-jasmine/

如果你觉得本文对你有帮助,请为我提供赞助 https://me.alipay.co,/jabez128

评论
发表评论
3年前
npm install -g protractor 
webdriver-manager update 
webdriver-manager start
3年前

不能编辑自己的评论么? npm install -g protractor webdriver-manager update webdriver-manager start

3年前

安装protractor的话就不需要再安装selenium了, 直接用下面三个命令就可以起selenium server npm install -g protractor webdriver-manager update webdriver-manager start

WRITTEN BY
张小俊128
Intern in Baidu mobile search department。认真工作,努力钻研,期待未来更多可能。
TA的新浪微博
PUBLISHED IN
Node.js测试研究

介绍Node.js的相关知识

我的收藏