欸! 我觉得自动化测试的架构应该长这样,测试应该这样写。

最近目前我的公司要做新的专案,
所以藉此需要一个新的专案来做自动化测试,
所以开始在思考一个好的自动化测试他的形状该长甚麽样子,
顺便分享一下如果我这菜鸡写自动化测试我会怎麽去构思以及怎麽写。
如果你有不同的想法也欢迎在底下留言跟我交流~

注意~ 这篇主要会以 Web UI 的 E2E 测试为主要测试范例,
API 等测试可能会有些许不同。

我这边以我自身经验和思考过後觉得它会长以下这样

feature

这边这部份很单纯是用来放测试很纯粹的测试,
不管你是用 robot framework 还是 nigtwatch
你都不应该把连续的步骤一个一个写进去测试里面你应该保持测试是乾净的,
比方说今天要测试一个简单的登入想必步骤会是以下这样。

  1. 打开浏览器
  2. 导向至登入页面
  3. 输入帐号
  4. 输入密码
  5. 点击登入
  6. 验证 (URL 或是相关的欢迎讯息)
  7. 登出
  8. 关闭浏览器

这样写有甚麽问题?

  1. 没办法直接看出来测试的目的
  2. 在其他相似的测试没办法重复利用
  3. 测试的时间拉长

看上面的步骤,
其实对於测试来说最重要的检查点在於点击登入这个动作後所出现的结果,
在前面的打开浏览器导向登入页面甚麽的都算是前置的动作,
这时我们可以透过 test hook 的形式将前面的步骤都模组化成一个动作,
可能叫做打开浏览器并导向至页面
那有前置动作就一定会有个结尾要做的事,
简单来说就是你前置动作的相反,
开浏览器相反就是把浏览器关掉
登入相反就是登出
那这边聪明的你就会想把结尾也包起来,
这边就是上面步骤的登出和关闭浏览器
所以此时测试会长得像是这样~

  1. [Setup] 打开浏览器并导向至页面
  2. 输入帐号
  3. 输入密码
  4. 点击登入
  5. 验证 (URL 或是相关的欢迎讯息)
  6. [Teardown] 登出并关闭浏览器

我们这边可以看到步骤已经减少了两步,
接着我们要思考点击登入前面的必要动作是不是可以被重复利用,
如果要测一个网站那想必登入这动作就是必须的所以这边我会将

  • 输入帐号
  • 输入密码
  • 点击登入

都包成一包叫做登入
这样测试就会变成以下这样。

  1. [Setup] 打开浏览器并导向至页面
  2. 登入
  3. 验证 (URL 或是相关的欢迎讯息)
  4. [Teardown] 登出并关闭浏览器

这样就会看起来很乾净~
而且你可以很清楚的看到测试的目的。

小总结:
测试应该保持乾净将需要验证前和验证後的步骤拆分成乾净,
拆分和包装时记得思考一下能不能被重复利用。

command

刚刚介绍完 featue 之後会想说包装起来的相关的动作要放在哪?
就是这里~

不管你做的连续动作是不是 UI 上面的操作,
只要是能被重复利用且清楚表达这些动作的目的你都应该要包起来放在这儿。
当你想写一个新的测试时应该要先寻找这边是不是有写好的相关步骤,
而不是一昧的...
写啦!
直接写了啦!
哪次不写!

我自身的习惯会是很共通的我可能会放在一个档案叫做 common
其他各自页面或是功能独有的会放在各自的档案。

lib

有时候我们操作一些 selenium 相关的动作没办法透过原生的方式进行,
或是你想透过 API 去完成一些事情减少测试在 UI 操作,
但却不是测试本身所需要测试的动作。
比方说...
上面的登入的测试想必还有一个前提是注册帐号
那如果说我将注册帐号这些动作都包装起来放在前置动作会发生甚麽事情?

  1. 他会大幅增加测试的时间
  2. 增加测试的失败机率而且不是测试本身该做的事情

你想想~
万一注册的 UI 有一些 bug 造成你这前置动作失败导致测试失败,
那这个测试要测的到底是注册还是登入啊?

你可能会想说...
不是阿! 我包也包了不然还有甚麽办法?
答案是... 你可以透过 API 的方式去完成这些事。

你可能又会想说讲的好像 API 就不会失败一样,
对!没错 API 也有可能会因为改动而造成测试失败,
但是相对从 UI 下手来说他有两个优点

  1. 他比 UI 快
  2. API 的改动频率正常来说比 UI 来的少

tests

我都在写测试了...
为甚麽我还要写测试的测试?
你有想过在你要求 RD 写 unit test 的同时,
你自己做的 libary 或是一些逻辑处理是没问题的吗?
我以前从来没有想过为了我自己测试写测试,
导致以前很常发生一件事

我: 欸那个... 某某部分坏了然後我看他回传的是....
开发: 我这边都没改欸... 我再查查 。

(过了半小时

我: 欸...我感到抱歉 QQ 是我这边写错我刚刚改了... ,所以是我这边的问题...
开发:

那这时候如果你有为了你的测试做测试的话你也不用担心发生这些尴尬的事情了xDDD

(关於为了测试写测试这部分有很大的争议,这边就不战到底该不该写,反正我是觉得该写。)

page_object

这是一个 design pattern ,
主要的用意是将页面相关的 element 跟程序做分离和统一控管,
如果你不这样做的话你可能会看到你的步骤里面充满着 xpath 和 css 的 selector...
这时候万一网页中其中一个元素改动你就必须...
去找吧! 我洒落在各地的 selector !
而且还有可能会发生这个按钮的定位有 xpath 和 css 和各种排列组合的出现,
这边会主要除了管理 selector 的部分之外还会统一定单纯一个步骤的动作
例如上面范例中的输入帐号输入密码点击登入都会在这边做实作
所以 command 基本上就是将 page_object 所弄好的单一动作组成一个 combo 连击的概念~

总结

看完之後你可能会想说...
欸不是阿你这架构可能会有@#$%$%&^$%#^的问题

我想说的是...
其实没有一个架构是完美的,
只有最符合你团队的架构 (干话)

分享给可能在构思自动化测试架构的你~
我之後可能会再补 Robot Framework 的 template (X

感谢您的收看
我是快被 dotnet core 搞疯的 Robin~
我们下次见

ps. 身为 QA 但是我好像第一次写关於 QA 的文章 ...
我深感抱歉xDD


<<:  《赖田捕手:追加篇》第 32 天:快速回覆 QuickReply 介绍

>>:  Day 28 - 强化学习 Reinforcement Learning(2)

Day21【Dev】物件类型:mutable 与 Immutable

mutable 与 Immutable 比较 Immutable object 不可变物件 物件被创...

[Day20] Tableau 轻松学 - Calculated Field

前言 Tableau Desktop 让我们不用写到一行程序就能进行资料探索,但不代表我们不能撰写程...

[Day_2] Python 资料型别与变数

资料型别 以下给大家介绍一些常用的资料型别,如下 : 符号 说明 False 布林值False 0 ...

Day 08 - Spring Boot 常用注释(上)

注释基本概念 注释(Annotations) 是Java 5.0 加入的新功能,它强化了程序注解与J...

Day-24 一定会见面,Convolutional Neural Network (CNN)

我们在历经了各种风霜之後,总算走到了这里,在深度学习的路上的必修课,也就是 Convolution...