测试PhoneGap应用程序
一、使用PhoneGap进行测试
在开发PhoneGap应用程序时,有一个名为PhoneGap Developer App的工具可以帮助我们快速测试Cordova/PhoneGap应用。使用该工具,我们可以在桌面端快速更改代码,并在连接的设备上测试应用,而无需通过IDE或CLI进行重建、重新安装或其他操作。其原理是通过共享网络将桌面和移动设备无线连接起来。
PhoneGap Developer App工具由两部分组成:
- 移动应用程序:它就像是我们应用的一个“外壳”。
- 移动PhoneGap应用本身:我们通过PhoneGap CLI的 phonegap serve 命令从计算机的Web服务器提供该应用。
移动部分的外观和行为就像我们安装在移动设备上的应用。在桌面端保存代码后,所有更改会立即在设备上反映出来。
1. PhoneGap Developer App设置步骤
- 安装PhoneGap:之前我们已经使用以下命令安装了PhoneGap:
$ sudo npm install -g phonegap
- 运行服务命令:进入之前创建的Cordova应用目录,例如“Crazy Bubble”应用:
$ cd crazy-bubbles2
$ phonegap serve
运行后,会在控制台看到应用服务器启动和监听的信息,例如:
[phonegap] starting app server...
[phonegap] listening on 192.168.0.102:3000
[phonegap]
[phonegap] ctrl-c to stop the server
[phonegap]
- 安装移动应用:从 http://app.phonegap.com/ 下载适用于iOS、Android和Windows Phone的移动应用。
- 连接设备:打开移动应用,在“Server Address”字段中输入控制台显示的IP地址和端口,例如“192.168.0.102:3000”,然后点击“Connect”。连接成功后,应用将在设备上运行。
2. 即时处理代码更改
我们可以打开喜欢的编辑器修改代码,保存后,所有更改会立即在设备上显示。在应用运行时,我们可以通过以下操作进行交互:
- 三指点击设备屏幕:返回主屏幕。
- 四指点击设备屏幕:使用更新后的内容重新加载应用。
如果在修改代码后没有看到文件重新加载,可以通过四指点击设备屏幕来重新加载应用。我们还可以为移动设备提供其他移动应用,只需使用 Ctrl + c 停止当前服务,进入下一个要运行的项目目录,然后再次运行 phonegap serve 命令,在设备上四指点击即可刷新屏幕显示新应用内容。
3. 包含核心插件
PhoneGap Developer App已经包含了PhoneGap核心插件,因此在快速测试一些原生功能时,我们无需向应用添加插件,这有助于避免在使用CLI开发和调试应用时忘记添加某些插件的问题。但在应用发布之前,我们仍然需要添加这些插件。不过, phonegap serve 目前不支持第三方插件。原因是配套PhoneGap Developer App需要使用每个插件的原生代码进行编译。希望这个问题能尽快得到改善,目前该工具仅允许使用纯JavaScript插件。
二、为什么我们需要测试
作为软件开发人员,我们开发各种应用,特别是移动应用。我们编写的数据可以在浏览器中运行,作为移动程序,或者作为Node.js脚本启动。在不同的情况下,我们期望得到特定的数据。每一行代码都有其意义,我们需要确保最终产品能够满足我们的需求。
通常我们会对应用进行调试,例如编写部分应用并运行它,使用不同调试工具和方法。有时我们会使用更复杂的工具,如GapDebug,或者简单方法,如视觉验收或 console.log 。通过监控输出或观察其行为,我们可以判断一切是否正常。然而,这种方法非常耗时,尤其是在项目规模较大且不断增长的情况下。反复测试应用的每个功能可能会耗费大量的时间和金钱。
自动测试在这种情况下可以提供帮助。测试对于编写更好的代码和组织架构非常有帮助。当系统复杂且模块之间存在大量关系时,添加新内容或进行重大更改会变得困难,我们无法保证修改后一切仍能正常工作。因此,与其依赖手动测试,不如创建脚本来为我们进行测试,这个过程也称为回归测试。编写测试有以下几个好处:
- 节省大量时间,因为我们不必反复进行手动测试。
- 测试证明我们的软件稳定且按预期运行。
- 编写不佳且依赖关系复杂的代码难以测试,编写测试有助于识别代码中存在问题的部分并进行修复。
- 如果我们有一个可靠的测试套件,就可以在不担心破坏现有功能的情况下扩展系统。
- 如果测试覆盖率足够高,测试可以作为代码的文档。
三、测试理论
1. 测试驱动开发(TDD)
测试驱动开发(TDD)依赖于短重复开发周期。这意味着我们在编写实现代码的同时编写测试。周期越短越好。TDD的流程如下:
graph LR
A[编写测试] --> B[运行测试(失败)]
B --> C[编写代码]
C --> D[运行测试(通过)]
D --> E[重构代码]
E --> A
在编写实际完成工作的代码之前,我们需要准备一个测试。第一次运行时,测试会失败,因为还没有实现任何功能。之后,我们需要逐周期地使测试通过。当测试通过后,我们可以花一些时间重构已完成的代码,然后继续处理下一个方法、类或功能。一切都从编写测试开始,这是一个很好的方法,因为我们在这个过程中定义了代码应该做什么。通过编写测试,我们可以避免编写和交付不需要的代码,并且确保实现满足需求。
TDD每个迭代需要遵循的步骤如下:
1. 添加测试。
2. 运行这些测试,检查是否至少有一个失败。
3. 编写一些代码。
4. 运行测试。
5. 重构代码。
6. 重复上述步骤。
还有一个相关的概念是验收测试驱动开发(ATDD),它是一种基于客户、开发人员和测试人员之间沟通的开发方法,处于比TDD更高的层次,包含了各种其他测试方法,例如行为驱动开发(BDD)。
2 . 行为驱动开发(BDD)
行为驱动开发与TDD类似。在小型项目中,我们很难区分它们。这种方法的理念是更关注应用中的规范和流程,而不是实际的代码。例如,在测试一个向博客发布消息的模块时:
- 使用TDD,我们可能会问:
- 消息是否为空?
- 用户是否已认证?
- POST请求是否正确发出?
- 返回的页面是否包含发布的数据?
- 使用BDD,我们会问:
- 消息是否已发送到博客?
这两个过程非常接近,在某些情况下,它们几乎没有区别。BDD方法处于更高的层次,客户也可以理解。我们需要记住的是,BDD关注代码实际做了什么,而TDD更关注代码是如何实现的。
四、测试分类
有许多不同类型的测试,下面介绍一些最常见的类型:
| 测试类型 | 描述 |
| ---- | ---- |
| 单元测试 | 对应用的单个部分进行检查,只关注代码的一个单元。但通常很难编写这样的测试,因为我们可能无法将代码拆分为单元,这对应用的可扩展性和维护性通常不利。如果没有明确定义的模块,就无法进行此类测试。将逻辑划分为不同单元不仅有助于测试,还有助于提高程序的整体稳定性。 |
| 集成测试 | 测试的输出是多个单元或组件的结果。这些单元通常是代码模块、独立应用、网络中的客户端和服务器部分等。集成测试通常使用系统的多个模块,确保它们能够正常协同工作。 |
| 功能测试 | 与集成测试非常接近,关注系统中的特定功能,即输出是否符合需求。它可能涉及多个模块或组件。 |
| 系统测试 | 将我们的程序置于不同的环境中。在PhoneGap的上下文中,这可能是在不同的移动平台上运行脚本并监控输出。有时会存在差异,如果我们想在全球范围内分发我们的应用,就需要确保它在最流行的平台上都能正常工作。 |
| 性能或压力测试 | 将应用置于超出定义规格的环境中,展示代码对高流量或复杂查询的反应。例如,类似于处理超出存储容量的大量数据、大量并发连接等。当我们需要决定程序的架构或选择框架时,这些测试非常有用。有许多不同的工具可用于进行性能和负载测试。 |
五、单元测试框架和测试运行器
如今有很多测试框架。一般来说,使用测试框架时,我们需要以下两个部分:
- 测试运行器:它是框架中运行我们的测试并显示测试通过或失败消息的部分。
- 断言:这些方法用于实际的检查。例如,如果我们需要检查一个变量 active 是否为 true ,可以使用 expect(active).toBe(true) ,而不是简单的 if(active === true) 。这不仅对测试的读者更友好,还可以避免一些奇怪的情况。例如,在以下代码中, if 语句会返回 true ,因为 status 变量有一个值,且该值为 null 。实际上,我们想问的是“ status 变量是否已初始化”,如果我们保持测试原样,会得到错误的结果。因此,我们需要一个具有适当测试方法的断言库:
var status = null;
if(typeof status != "undefined") {
console.log("status is defined");
} else {
console.log("status is not defined");
}
一些流行的JavaScript测试框架如下:
- QUnit:一个jQuery测试工具。
- Mocha:一个完整的JavaScript测试框架。
- JSSpec:一个行为驱动开发框架。
- Jasmine:一个行为驱动开发框架,允许我们进行无DOM测试和异步测试。
下面我们将以Jasmine框架为例,结合无头浏览器PhantomJS,对“Imaginary”应用进行BDD测试。
六、使用Jasmine和无头浏览器PhantomJS进行测试
1. Jasmine简介
Jasmine既可以作为Node.js模块使用,也可以作为库在浏览器中使用,它自带了断言方法。可以通过Node.js包管理器npm进行安装:
$ npm install jasmine-node -g
该命令会全局安装Jasmine,这样我们可以在任何目录中运行 jasmine-node 。测试可以组织成不同的文件,放在一个文件夹或子文件夹中,文件名必须以 spec.js 结尾,例如 testing-picture-capture.spec.js 或 testing-picture-list.spec.js 。
2. 使用Jasmine编写单元测试
假设我们要构建一个读取文件内容并查找特定单词“dolor”的应用。首先,创建项目结构:
.
├── app.js
├── intro.txt
└── tests
└── test.spec.js
我们将测试应用的代码放在 tests/test.spec.js 中,逻辑实现放在 app.js 中,要读取的文件是 intro.txt 。在 intro.txt 中添加一些“lorem ipsum”文本。
我们将按照TDD方法,将代码分为两个不同的函数,并为每个函数编写测试:
- 读取文件内容。
- 在文件内容中搜索特定单词。
以下是使用Jasmine编写的测试代码:
describe("Testing the reading of the file's content.", function() {
it("should require of app.js", function(done) {
var app = require("../app.js");
expect(app).toBeDefined();
done();
});
it("should read the file", function(done) {
var app = require("../app.js");
var content = app.read("./intro.txt");
expect(content).toBe("Lorem ipsum dolor sit amet, diceret percipit ea cum, porro vituperata comprehensam usu ea, tation fastidii molestiae eu nam.");
done();
});
});
运行测试:
$ jasmine-node ./tests
第一次运行时,第二个测试会失败,因为 app.js 中没有 read 方法。我们在 app.js 中添加以下代码:
module.exports = {
read: function() {
}
}
再次运行测试,仍然会失败,因为 read 方法没有返回任何内容。我们继续修改 app.js :
var fs = require('fs');
module.exports = {
read: function(filePath) {
return fs.readFileSync(filePath).toString();
}
}
此时,测试通过,显示为绿色。
为了测试是否能在文本中找到特定单词,我们添加以下测试代码:
describe("Testing if the file contains certain words", function() {
it("should contains 'dolor'", function(done) {
var app = require("../app.js");
var found = app.check("dolor", "Lorem ipsum dolor sit amet");
expect(found).toBe(true);
done();
});
});
运行测试会失败,因为 app.js 中没有 check 方法。我们在 app.js 中添加 check 方法:
var fs = require('fs');
module.exports = {
//...
check: function(word, content) {
return content.indexOf(word) >= 0 ? true : false;
}
}
再次运行测试,测试将通过。
通过以上步骤,我们可以看到如何使用Jasmine和PhantomJS进行单元测试,遵循TDD方法可以帮助我们编写更健壮的代码。同时,PhoneGap Developer App为我们提供了便捷的测试环境,让我们可以快速验证代码的更改。不同类型的测试和测试框架可以根据项目的需求进行选择和组合,以确保应用的质量和稳定性。
测试PhoneGap应用程序
七、持续集成与测试自动化
在实际的项目开发中,持续集成(CI)和测试自动化是非常重要的环节。持续集成是一种软件开发实践,团队成员频繁地将代码集成到共享的代码库中,每次集成都通过自动化的构建(包括编译、发布、自动化测试等)来验证,从而尽早地发现集成错误。
结合前面提到的测试方法和工具,我们可以搭建一个自动化的测试流程。例如,使用Jenkins这样的持续集成工具,结合Jasmine和PhantomJS进行自动化测试。以下是一个简单的步骤说明:
- 安装Jenkins :可以从Jenkins的官方网站下载并安装,安装完成后,启动Jenkins服务。
- 配置Jenkins :在Jenkins的管理界面中,安装必要的插件,如Git插件、NodeJS插件等。
- 创建任务 :在Jenkins中创建一个新的自由风格的软件项目。
- 配置代码仓库 :在任务配置中,指定代码仓库的地址,如Git仓库。
- 配置构建环境 :使用NodeJS插件,指定NodeJS的安装路径,确保可以使用npm安装依赖。
- 配置构建步骤 :在构建步骤中,添加执行shell脚本的步骤,脚本内容如下:
# 安装依赖
npm install
# 安装Jasmine
npm install jasmine-node -g
# 运行测试
jasmine-node ./tests
- 配置构建后操作 :可以配置邮件通知等,当测试失败时,及时通知开发人员。
通过这样的配置,每次代码提交到仓库时,Jenkins会自动拉取代码,安装依赖,运行测试,并将测试结果反馈给开发人员。
八、测试的最佳实践
在进行PhoneGap应用测试时,有一些最佳实践可以帮助我们提高测试效率和质量。
1. 分层测试
将测试分为不同的层次,如单元测试、集成测试、功能测试等。单元测试关注代码的最小可测试单元,集成测试关注模块之间的交互,功能测试关注系统的整体功能。这样可以确保每个层次的代码都得到充分的测试。
2. 数据驱动测试
使用不同的数据集来运行测试,以覆盖更多的场景。例如,在测试文件读取功能时,可以使用不同的文件内容和文件名进行测试。
3. 并行测试
对于一些独立的测试用例,可以并行运行,以节省测试时间。例如,使用测试框架的并行运行功能,或者在多个设备上同时运行测试。
4. 定期维护测试用例
随着项目的发展,代码会不断变化,测试用例也需要相应地更新和维护。定期检查测试用例的覆盖率,删除无效的测试用例,添加新的测试用例。
九、总结与展望
通过本文的介绍,我们了解了如何使用PhoneGap Developer App快速测试PhoneGap应用,以及为什么需要测试和不同的测试理论、分类和框架。测试是软件开发过程中不可或缺的一部分,它可以帮助我们提高代码质量,减少错误,节省时间和成本。
在未来的开发中,随着移动应用的不断发展,测试的需求也会越来越高。我们需要不断学习和掌握新的测试技术和工具,如人工智能辅助测试、基于云计算的测试平台等。同时,我们也需要注重测试的质量和效率,确保测试能够真正为项目的成功做出贡献。
总之,测试是一个不断发展和完善的过程,我们需要不断探索和实践,以适应不断变化的软件开发环境。
graph LR
A[开始] --> B[持续集成配置]
B --> C[分层测试]
C --> D[数据驱动测试]
D --> E[并行测试]
E --> F[维护测试用例]
F --> G[结束]
| 最佳实践 | 描述 |
|---|---|
| 分层测试 | 将测试分为单元、集成、功能等层次,确保各层次代码充分测试 |
| 数据驱动测试 | 使用不同数据集运行测试,覆盖更多场景 |
| 并行测试 | 并行运行独立测试用例,节省时间 |
| 定期维护测试用例 | 随项目发展更新和维护测试用例,保证覆盖率 |
通过以上的总结和展望,希望能够为开发者在PhoneGap应用测试方面提供一些有益的参考和指导。
超级会员免费看
32

被折叠的 条评论
为什么被折叠?



