2

FEAT

FrontEnd Automates Test 前端全自动化测试

序章

文章开头先引一个知乎上的问答:如何进行前端自动化测试?

我相信做过前端的朋友都有这个疑问。希望这篇文章里你能看到一些别人的测试方法,帮助你更好的进行测试工作;

很尴尬的是,在此之前我的开发测试也都不会有单元测试而都是人肉测试,对不起自己 ☹️;

为了以后能够更好的进行测试工作,记录自己测试学习的过程,希望能帮自己也能帮到别人。


做测试,应该从哪里开始切入呢

做测试的俩个要素
  • 程序:我们往常写的代码
  • 测试用例:测试你的代码的输入输出是否符合预期
一个简单的测试

假如有这样一个俩数相加的程序功能:

function add(a, b){
 return a+b
}

clipboard.png

我们现在要对这个俩数相加的程序功能进行测试,来测试这个 add 方法的输入输出是否符合我们的预期,那就要去写测试用例去测试。

那么我们的测试用例怎么写呢

方式一:你可能这么写

5 === add(2, 3) // 测试用例(1)
(1.7976931348623157e+308 * 2) !== add(1.7976931348623157e+308, 1.7976931348623157e+308 + 1) // 测试用例(2)

测试用例(1)用预期的 5 和 add 方法输入 2 和 3 的输出结果进行比对,是否相等;如果相等,那么 add 方法就通过测试用例,如果不等,就证明我们的 add 方法存在问题。
可以看到测试用例(1)
clipboard.png
结果是相等,通过测试
测试用例(2)用预期的 1079654173767686669 和 add 方法输入 1.7976931348623157e+308 和 1.7976931348623157e+308 的输出结果进行和用例(1)一样的操作。
可以看到测试用例(2)
clipboard.png
结果应该不等, 测试不通过

原因:原来是我们没有考虑大数相加结果溢出的情况,所以我们的 add 方法是只能在相加的结果不会溢出情况下得到期望的正确结果。

我们就有必要对我们的方法进行改动以适配大数相加,那么每一次这个方法的改动,我们就要执行一次上面的测试用例。这样我们就能进行我们的而测试工作了。

如果应对简单的需求这样的方式显然够用了,但是事实上应该是没人会这么写测试用例的。
大家会用 nodejs 提供的 assert 模块或者 shouldjs 这类断言库来帮我们做断言这件事情;而且这些模块被 node 原生提供支持,后面要在此测试基础上进行自动化测试,生成测试报告之类的,都非常方便。

下节我们以 assert 模块为例来改造这个测试用例;这一节我们先做一些准备工作,要写测试用例,会用到断言,那么我们这节就先看看断言的相关内容,以 node 的 Assert 模块为例:

Assert 模块

assert 模块提供了断言测试的函数,用于测试不变式。

assert.AssertionError 类

Error 的一个子类,表明断言的失败。 assert 模块抛出的所有错误都是 AssertionError 类的实例。
这是我们写测试用例,执行测试,调试测试过程最常见到的一个类,指示遇到断言失败。

assert构造函数

assert(value[, message])

assert.ok() 的别名

assert.deepEqual(actual, expected[, message]) 已废弃

附:assert.deepStrictEqual() 的别名

deepStrictEqual

assert.deepStrictEqual(actual, expected[, message])

测试 actual 参数与 expected 参数是否深度相等。 深度相等意味着子对象中可枚举的自身属性也会按以下规则递归地比较。
assert.deepStrictEqual({a:1}, {a:1}); //这样的测试是可以通过的

注意:脚本中这俩个是不绝对相等的
clipboard.png

doesNotReject

assert.doesNotReject(block, error)

该函数相当于 assert.doesNotThrow(),除了需要等待完成的异步特性。
等待 block 的 promise 完成,如果 block 是一个函数,则立即调用该函数并等待返回的 promise 完成,然后检查 promise 是否被 reject。
如果 block 是一个函数且同步地抛出一个错误,则 assert.doesNotReject() 会返回一个被 reject 的 Promise 并传入该错误。 如果该函数没有返回一个 promise,则 assert.doesNotReject() 会返回一个被 reject 的 Promise 并传入 ERR_INVALID_RETURN_VALUE 错误。 以上两种情况都会跳过错误处理函数。

doesNotThrow

assert.doesNotThrow(block, error)

断言 block 函数不会抛出错误。
当 assert.doesNotThrow() 被调用时,它会立即调用 block 函数。
如果抛出错误且错误类型与 error 参数指定的相同,则抛出 AssertionError。 如果错误类型不相同,或 error 参数为 undefined,则抛出错误。

assert.equal(actual, expected[, message]) 已废弃

附:assert.strictEqual() 的别名。

fail

assert.fail([message])

抛出 AssertionError,并带上提供的错误信息或默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。

assert.fail(actual, expected[, message[, operator[, stackStartFunction]]]) 已废弃

附:使用 assert.fail([message]) 代替。

ifError

assert.ifError(value)

如果 value 不为 undefined 或 null,则抛出 value。 可用于测试回调函数的 error 参数。 堆栈踪迹会包含传入 ifError() 的错误的所有帧,包括潜在的 ifError() 自身新增的帧。

assert.notDeepEqual(actual, expected[, message]) 已废弃

附:使用 assert.notDeepStrictEqual() 代替。

notDeepStrictEqual

assert.notDeepStrictEqual(actual, expected[, message])

测试 actual 参数与 expected 参数是否不深度全等。 与 assert.deepStrictEqual() 相反。
附:assert.notStrictEqual() 的别名。

assert.notEqual(actual, expected[, message]) 已废弃

附:使用 assert.notStrictEqual() 代替。

notStrictEqual

assert.notStrictEqual(actual, expected[, message])

使用 SameValue 比较法测试 actual 参数与 expected 参数是否不全等。

ok

assert.ok(value[, message])

测试 value 是否为真值。 相当于 assert.equal(!!value, true, message)。

rejects

assert.rejects(block, error)

等待 block 的 promise 完成,如果 block 是一个函数,则立即调用该函数并等待返回的 promise 完成,然后检查 promise 是否被 reject。

如果 block 是一个函数且同步地抛出一个错误,则 assert.rejects() 会返回一个被 reject 的 Promise 并传入该错误。 如果该函数没有返回一个 promise,则 assert.rejects() 会返回一个被 reject 的 Promise 并传入 ERR_INVALID_RETURN_VALUE 错误。 以上两种情况都会跳过错误处理函数。

strictEqual

assert.strictEqual(actual, expected[, message])

使用 SameValue 比较法测试 actual 参数与 expected 参数是否全等。

throws

assert.throws(block, error)

断言 block 函数会抛出错误。

至此,断言模块所有的 api 我们都清楚了,当然 node 官网对于Assert 模块还有更详细的内容。


言月
1.8k 声望490 粉丝

从有技术广度到技术深度的转变,这样才能被自己迷恋