当前位置: 代码迷 >> JavaScript >> 运用PhantomJS测试JavaScript
  详细解决方案

运用PhantomJS测试JavaScript

热度:580   发布时间:2012-12-23 11:28:15.0
使用PhantomJS测试JavaScript

使用PhantomJS测试JavaScript

教程说明
    • 主题 :PhantomJS
    • 难度 :容易
    • 预计完成时间 :30分钟

我认为我不需要说服你,测试你的JavaScript代码是一个好主意。但是,测试需要DOM操作的JavaScript代码有时候确是繁琐的。这意味着你需要在浏览器中测试代码而不能使用终端,对吗?错了,事实是:进入PhantomJS 。


究竟PhantomJS是什么?好吧,这有一个来自PhantomJS网站的简介:

PhantomJS是一个拥有JavaScript API的无界面WebKit。

正如你所知道的,Webkit是Chrome、Safari和其他一些小众浏览器使用的布局引擎。因此,PhantomJS是一个浏览器,而且是一个无界面的浏览器。这意味着,渲染后的网页实际上绝不会显示。这对你来说可能不可思议,所以你可以把它作为一个可编程的浏览器终端。我们马上将看一个简单的例子,但首先需要安装PhantomJS。


安装PhantomJS

安装PhantomJS事实上很简单:你下载的仅仅是单独的一个二进制文件,接着将文件路径粘帖到终端。在PhantomJS下载页面 ,选择您的操作系统并下载正确的软件包。接着,将二进制文件从下载的程序包中移动到一个在你终端路径的目录中(我喜欢把这类玩意放到~/bin里)。

如果你用的是Mac OS X,有一个更简单的方法安装PhantomJS(这实际上是我所使用的方法)。只需像这样使用Homebrew:

brew update && brew install phantomjs

你现在应该已经安装了PhantomJS。你可以运行以下命令仔细检查安装信息:

phantomjs --version

我看到1.7.0,你呢?


一个简单的例子

让我们先从一个简单的例子开始吧

simple.js
console.log("we can log stuff out.");
function add(a, b) {
    return a + b;
}
conslole.log("We can execute regular JS too:", add(1, 2));
phantom.exit();

继续前进,发出以下命令运行这段代码:

phantomjs simple.js

你应该在终端窗口中看到来自两行console.log的输出。

当然,这很容易,但它证明了一个很不错的点:PhantomJS可以像一个浏览器那样执行JavaScript。然而,这个例子并没有任何特定于PhantomJS的代码......好吧,除了最后一行。那行代码对于每个PhantomJS脚本都很重要,因为它退出脚本执行。这可能说不通,但要记住,JavaScript并不总是顺序执行。例如,你可能想要把exit()的调用放在一个回调函数中 。

让我们看一个更复杂的例子。


加载页面

通过使用PhantomJS API,我们可以加载任何URL,并从两个维度来与页面工作:

  • 作为页面上的JavaScript。
  • 作为一个正在浏览页面的用户。

让我们从选择加载页面开始。创建一个新的脚本文件,并添加下面代码:

script.js
var page = require('webpage').create();
page.open('http://net.tutsplus.com', function (s) {
    console.log(s);
    phantom.exit();
});

我们首先加载PhantomJS的webpage模块并创建一个webpage对象。接着,我们调用open方法,传递给它一个URL和一个回调函数;正是在这个回调函数内部,我们可以与实际的页面交互。在上面的例子中,我们只是记录由回调函数的参数提供的请求状态。如果你运行这个脚本(用phantomjs script.js ),你看到终端打印出“成功”。

但是,让我们加载一个网页,并执行一些JavaScript代码,把这变得更加有趣些。我们从上面的代码开始,接着调用page.evaluate :

page.open('http://net.tutsplus.com', function () {
    var title = page.evaluate(function () {
        var posts = document.getElementsByClassName("post");
        posts[0].style.backgroundColor = "#000000";
        return document.title;
    });
    page.clipRect = { top: 0, left: 0, width: 600, height: 700 };
    page.render(title + ".png");
    phantom.exit();
});

PhantomJS是一个浏览器,但是是一个无界面的浏览器。

我们传递给page.evaluate的函数在加载的网页上作为JavaScript执行。在这个用例中,我们找到的所有元素带post类的元素;接着,我们设置集合中第一个元素的背景为黑色。最后,我们返回document.title 。这是一个很好的功能,从evaluate回调函数中返回值,并将其分配给一个变量(在这里是 title )。

然后,我们在页面上设置clipRect;这是给render方法提供的屏幕截图尺寸。正如你所见,我们设置topleft值来设置起点,并且我们还设置了widthheight 。最后,我们调用page.render ,传给它一个文件名( title变量)。接着,我们调用phantom.exit()结束脚本

继续运行这个脚本,你应该拥有一副看起来像这样的图片:

在这里,你可以看到PhantomJS这枚硬币的两面:可以在页面内执行JavaScript,还可以针对页面实例自身从外部执行。

这很有趣,但不是很有用。让我们将目光集中在使用PhantomJS测试DOM相关的JavaScript。


用PhantomJS测试

Yeoman在其测试过程中使用PhantomJS,并且它几乎是无缝的。

对于很多的JavaScript代码,你可以不依赖DOM测试,但也有那么些时候,你的测试用例需要HTML元素一起工作。如果你像我一样,喜欢在命令行上运行测试用例,这就是PhantomJS的用武之地。

当然,PhantomJS是不是一个测试库,但许多其他流行的测试库可以运行在PhantomJS中。正如你可以从PhantomJS wiki页面关于无界面测试中所看到的,PhantomJS的测试驱动可用于几乎每一个你可能想使用的测试库。让我们来看看如何与Jasmine及Mocha一起使用PhantomJS。

首先, Jasmine和一个免责声明:现在并没有一个优秀的用于Jasmine的PhantomJS驱动。如果你使用Windows和Visual Studio,你应该去check outChutzpah ,Rails开发人员应该试试guard-jasmine 。但除此之外,对Jasmine+ PhantomJS的支持非常稀疏。

出于这个原因,我建议你使用Mocha进行D??OM相关的测试。

尽管如此,很可能你已经有一个项目在使用Jasmine ,并想与PhantomJS一起使用。一个叫 phantom-jasmine的项目 ,需要一点点的设置工作,但它应该能够达到目的。

让我们从一组JasmineJS测试用例开始。下载本教程的代码(在顶部的链接),并check outjasmine-starter文件夹。你会看到,我们有一个单独的tests.js文件,该文件创建一个DOM元素,设置了DOM元素的几个属性,并将其添加到body中。然后,我们运行一些Jasmine 测试用例,以确保这个过程确实的正常工作。下面是该文件的内容:

tests.js
describe("DOM Tests", function () {
    var el = document.createElement("div");
    el.id = "myDiv";
    el.innerHTML = "Hi there!";
    el.style.background = "#ccc";
    document.body.appendChild(el);
    var myEl = document.getElementById('myDiv');
    it("is in the DOM", function () {
        expect(myEl).not.toBeNull();
    });
    it("is a child of the body", function () {
        expect(myEl.parentElement).toBe(document.body);
    });
    it("has the right text", function () {
        expect(myEl.innerHTML).toEqual("Hi there!");
    });
    it("has the right background", function () {
        expect(myEl.style.background).toEqual("rgb(204, 204, 204)");
    });
});

SpecRunner.html文件是相当树干;唯一的区别是,我将脚本标签移到body中,以确保DOM在运行我们的测试前完全加载。你可以在浏览器中打开该文件,并看到所有的测试都很好的通过了。

让我们把这个项目过渡到PhantomJS。首先,克隆phantom-jasmine项目:

git clone git://github.com/jcarver989/phantom-jasmine.git

该项目并不是那么的有组织,但它有两个重要的组成部分是你所需要的:

  • PhantomJS驱动(这使得Jasmine 能够使用PhantomJS DOM)。
  • Jasmine 控制台报告器(这提供控制台输出)。

这两个文件中都属于lib文件夹,将其复制到jasmine-starter/lib 。现在,我们需要打开SpecRunner.html文件,并调整<script />元素。它们应该像这样:

<script src="lib/jasmine-1.2.0/jasmine.js"></script>
<script src="lib/jasmine-1.2.0/jasmine-html.js"></script>
<script src="lib/console-runner.js"></script>
<script src="tests.js"></script>
<script>
    var console_reporter = new jasmine.ConsoleReporter()
    jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
    jasmine.getEnv().addReporter(console_reporter);
    jasmine.getEnv().execute();
</script>

请注意,我们的测试中有两个报告器:HTML报告器和一个控制台报告器。这意味着SpecRunner.html和它的测试可以运行在浏览器和控制台。这非常方便。不幸的是,我们确实需要有console_reporter变量,因为它在内部被用于我们即将运行的CoffeeScript文件,。

那么,如何在控制台上真实的运行这些测试呢?假设你的终端当前目录是jasmine-starter文件夹,以下是这些命令:

phantomjs lib/run\_jasmine\_test.coffee ./SpecRunner.html

我们正在使用PhantomJS运行run\_jasmine\_test.coffee脚本,并将SpecRunner.html文件作为参数传递。你应该会看到这样的内容:

当然,如果一个测试用例失败,你会看到类似以下内容:

如果你打算经常使用这货,将 run\_jasmine\_test.coffee移动到另一个位置(比如~/bin/run\_jasmine\_test.coffee )也许是一个好主意,并为整个命令创建一个终端别名。这里告诉了你如何在Bash shell中做到这一点:

alias phantom-jasmine='phantomjs /path/to/run\_jasmine\_test.coffee'

只需丢在你的.bashrc.bash_profile文件里。现在,你可以只运行:

phantom-jasmine SpecRunner.html

现在你的Jasmine测试通过PhantomJS在终端上运行良好。你可以在下载文件夹中的jasmine-total看到最终的代码。


PhantomJS和Mocha

值得庆幸的是,使用mocha-phantomjs整合Mocha与PhantomJS更加容易。如果你已经安装了NPM(你应该要安装),那么安装mocha-phantomjs则是超级容易:

npm install -g mocha-phantomjs

此命令安装一个mocha-phantomjs二进制文件,我们将用它来运行我们的测试。

在前面的教程中 ,我向你展示了如何在终端使用Mocha,但当你用它来??测试DOM代码时,你会做些不同的事情。与Jasmine一样,我们将以一个可以运行在浏览器中的HTML测试报告器开始。美妙的是,对于控制台测试结果,我们可以用PhantomJS在终端上运行同一个文件;正如我们使用Jasmine那样。

那么,让我们创建一个简单的工程。创建一个工程目录,并切换到它的路径。我们以一个package.json文件为开始:

{
    "name": "project",
    "version": "0.0.1",
    "devDependencies": {
        "mocha": "*",
        "chai" : "*"
    }
}

Mocha是测试??框架,我们将使用Chai作为我们的断言库。我们运行NPM安装这些。

我们将测试文件命名为test/tests.js ,这里是它的测试用例:

describe("DOM Tests", function () {
    var el = document.createElement("div");
    el.id = "myDiv";
    el.innerHTML = "Hi there!";
    el.style.background = "#ccc";
    document.body.appendChild(el);
    var myEl = document.getElementById('myDiv');
    it("is in the DOM", function () {
        expect(myEl).to.not.equal(null);
    });
    it("is a child of the body", function () {
        expect(myEl.parentElement).to.equal(document.body);
    });
    it("has the right text", function () {
        expect(myEl.innerHTML).to.equal("Hi there!");
    });
    it("has the right background", function () {
        expect(myEl.style.background).to.equal("rgb(204, 204, 204)");
    });
});

它们与Jasmine的测试用例非常相似,但是Chai 断言语法则是有点不同的(所以,不要只是复制你的Jasmine测试用例)。

最后一道难题是TestRunner.html文件:

<html>
    <head>
        <title> Tests </title>
        <link rel="stylesheet" href="./node_modules/mocha/mocha.css" />
    </head>
    <body>
        <div id="mocha"></div>
        <script src="./node_modules/mocha/mocha.js"></script>
        <script src="./node_modules/chai/chai.js"></script>
        <script>
            mocha.ui('bdd');
            mocha.reporter('html');
            var expect = chai.expect;
        </script>
        <script src="test/test.js"></script>
        <script>
            if (window.mochaPhantomJS) { mochaPhantomJS.run(); }
            else { mocha.run(); }
        </script>
    </body>
</html>

这里有几个重要的因素。首先,请注意这是完全能够运行在浏览器中的,我们拥有从安装的node模块中的CSS和JavaScript。接着,注意内联的script标签。这将确定PhantomJS是否加载,若加载,则运行PhantomJS的的功能。否则,它使用原生的Mocha功能。你可以尝试在浏览器中运行,并观察它的工作。

要在控制台运行,只需执行以下命令:

mocha-phantomjs TestRunner.html

瞧!现在你的测试用例在控制台中运行,这一切都归功于PhantomJS。


PhantomJS和Yeoman

我敢打赌,你肯定不知道流行的Yeoman在其测试过程中使用PhantomJS,并且这几乎是无缝的。让我们看一个迅速的例子。我将假设你已经将Yeoman的一切设置好了。

创建一个新的工程目录,运行里面的yeoman init ,并对所有选项选择“NO”。打开test/index.html文件,你会发现接近底部有一个脚本标签,脚本中有一段注释告诉你将其替换成你自己的用例。完全的忽略那个很好的建议,并把下面这些放到 it块中:

var el = document.createElement("div");
expect(el.tagName).to.equal("DIV");

现在,运行yeoman test ,你会看到测试运行得相当好。现在,在浏览器中打开test/index.html文件。它运作了!完美!

当然,你还可以用Yeoman做更多的事,所以check out出它的文档做更深一步的了解。


结论

使用扩展于PhantomJS的库,使你的测试更加容易。

如果你正在使用PhantomJS,学习PhantomJS是毫无任何理由的,你可以只知道它的存在和使用扩展于PhantomJS的库来使你的测试更加容易。

希望本教程已经激发了你去观察PhantomJS的兴趣。我建议从PhantomJS提供的示例文件和文档开始 ;它们真的会打开你的视野,让你知道你可以用PhantomJS做什么――从页面自动化到网络嗅探的任何事情。

那么,你能想到一个能够用PhantomJS改进的项目吗?让我们在评论中听听!

原文链接:http://net.tutsplus.com/tutorials/javascript-ajax/testing-javascript-with-phantomjs/

  相关解决方案