驱动测试

如果你对驱动开发还没有了解,请参考驱动开发起步走驱动编程模型

传统硬件驱动测试

在传统的硬件开发中,驱动测试除了要编写一个测试应用之外,还要把这个应用打包成目标镜像,烧写到目标硬件上。因为通常镜像文件比较大,所以,烧写文件的过程通常以分钟计,多者甚至长达几十分钟。

如果只是最终的集成测试过程,这么做是可以接受的。但通常在开发过程中,开发者进行的测试通常是一些应用逻辑的测试。如果这样的测试也只能在硬件上进行,无疑浪费了大量的时间。

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 机制支持的。