如果你对驱动开发还没有了解,请参考驱动开发起步走和驱动编程模型。
传统硬件驱动测试
在传统的硬件开发中,驱动测试除了要编写一个测试应用之外,还要把这个应用打包成目标镜像,烧写到目标硬件上。因为通常镜像文件比较大,所以,烧写文件的过程通常以分钟计,多者甚至长达几十分钟。
如果只是最终的集成测试过程,这么做是可以接受的。但通常在开发过程中,开发者进行的测试通常是一些应用逻辑的测试。如果这样的测试也只能在硬件上进行,无疑浪费了大量的时间。
Ruff 驱动测试
Ruff 致力于简化硬件开发过程,它提供一个 Driver Runner 和模拟接口作为驱动测试的基础设施,如此一来,大多数驱动的逻辑测试部分就可以在开发机上完成,省去了每次部署到硬件的繁琐过程。var assert = require('assert');
var runner = require('ruff-driver-runner').runner;
var when = require('ruff-mock').when;
export['test should work well'] = function(done) {
runner.run('../', function(error, context) {
var device = context.device;
var gpio = context.inputs['gpio'];
when(gpio)
.read(Function)
.then(function (callback) {
callback(undefined, 1);
});
device.readValue(function (error, value) {
assert.ifError(error);
assert.equal(value, 1);
done();
});
}
}
require('test').run(exports);
(test/driver-test.js)
运行如下命令执行测试:ruff test/driver-test.js
这里用到的是几个框架:
- ruff-driver-runner,是 Ruff 提供的驱动测试框架,它就是前面提到的 Driver Runner,所有的设备都已经由模拟对象替代,保证可以在开发机上执行。
- ruff-mock,是 Ruff 提供的一个通用 mock 框架,也是模拟接口的基础。
- 一个简单的测试框架(
test
),符合 CommonJS 的 Unit Testing 规范。
下面会分别介绍一下 Driver Runner 和模拟接口,这是 Ruff 应用测试的两个核心概念。
Driver Runner
Driver Runner 是 Ruff 提供的一个模拟运行环境,让驱动可以在没有硬件的情况下执行。其基本用法如下所示:var runner = require('ruff-driver-runner');
runner.run('../', function(error, context) {
// your test code when your driver is ready
var device = context.device;
var gpio = context.inputs['gpio'];
});
其中,
Driver Runner 的 run(driverPath, callback)
函数有两个参数,其中, driverPath
就是驱动的工程所在路径, Driver Runner 会加载相应的工程配置,另一个是一个函数,就是我们要运行的代码。这个函数要接受两个参数:
error
,可能的异常。context
,我们可以从中得到一些配置信息,包括设备context.device
及接口context.inputs
。
模拟接口
模拟接口是 Ruff 保证硬件驱动运行在开发机上的一种解决方案,它对接口的基本 API 提供了很好的支持:
- 模拟数据返回,比如,GPIO 口返回1。
- 验证硬件行为,比如,GPIO 口设置为1。
- 触发驱动事件,模拟某些中断行为,比如,GPIO 产生中断事件。
其中,模拟数据返回和验证硬件行为是由 ruff-mock
支持,触发驱动事件是由 event
机制支持的。