—— 出处:《ThoughtWorks 的敏捷测试》
所有人应该对质量负责:
从流程上来说:
自动化测试框架组成:
又被称之为黑盒测试,包含了:
来源:《一页纸测试策略》
质量内建,旨在软件交付过程的早期发现并预防缺陷,将任务移动到软件开发生命周期的左侧来提高质量,测试人员可以从需求分析阶段开始介入。
测试过慢
Given-When-Then 表达方式可以称之为一个公式一个模板,这种方式旨在指导程序员为“用户故事”编写测试用例变得方便。
E2E 定义示例:
Given('当我在网站的首页', function () {
return this.driver.get('http://0.0.0.0:7272/');
});
When('输入用户名 {string}', function (text) {
return this.driver.findElement(By.id('username_field')).sendKeys(text);
});
When('输入密码 {string}', function (text) {
return this.driver.findElement(By.id('password_field')).sendKeys(text);
});
When('提交登录信息', function () {
return this.driver.findElement(By.id('login_button')).click();
});
Then('用户应该跳转到欢迎页', function () {
this.driver.getTitle().then(function (title) {
expect(title).to.equal('Welcome Page');
});
});
Then('页面应该返回 {string}', function (string) {
this.driver.getTitle().then(function (title) {
expect(title).to.equal(string);
});
});
JUnit 示例:
@Test
public void shouldReturnItemNameInUpperCase() {
// Given
Item mockedItem = new Item("it1", "Item 1", "This is item 1", 2000, true);
when(itemRepository.findById("it1")).thenReturn(mockedItem);
// When
String result = itemService.getItemNameUpperCase("it1");
// Then
verify(itemRepository, times(1)).findById("it1");
assertThat(result, is("ITEM 1"));
}
有时候对被测系统(SUT)进行测试是很困难的,因为它依赖于其他无法在测试环境中使用的组件。这有可能是因为这些组件不可用,它们不会返回测试所需要的结果,或者执行它们会有不良副作用。在其他情况下,我们的测试策略要求对被测系统的内部行为有更多控制或更多可见性。 如果在编写测试时无法使用(或选择不使用)实际的依赖组件(DOC),可以用测试替身来代替。测试替身不需要和真正的依赖组件有完全一样的的行为方式;他只需要提供和真正的组件同样的 API 即可,这样被测系统就会以为它是真正的组件! ——Gerard Meszaros
类型 | 解释 |
---|---|
Dummy Object | 不包含实现的对象(Null 也是),在测试中需要传入,但是它没有被真正地使用,通常它们只是被用来填充参数列表。 |
Fake | 有具体实现的,但是实现中做了些捷径,使它们不能应用与生产环境(举个典型的例子:内存数据库) |
Stub | 状态验证。返回固定值的实现 |
Spy | 行为验证。类似于 Stub,但会记录被调用那些成员,以确定 SUT(System Under Test)与它的交互是否是正确的 |
Mock | 由 Mock 库动态创建的,能提供类似 Dummy、Stub、Spy 的功能。开发人员看不到 Mock object 的代码,但可以设置 Mock object 成员的行为及返回值。 |
Mock 和 Stub 就是常见的两种方式:
示例见:《测试替身》
测试自动化应该遵循的简单规则
规则 | 理由 |
---|---|
单一职责 | 易于调试:业务规则变更时易于修改 |
不要重复自己 | 能够只改一个地方 |
使用领域特定语言 | 使测试人员相关的沟通更加容易 |
抽象测试 | 使测试更加易读 |
设置和清除(setup & teardown | 可以重复执行测试 |
避免访问数据库(尽可能) | 访问数据库会使测试变慢(注意,有些情况还是需要访问数据库的) |
测试必须一直保持绿色 | 保证测试的信心:活文档 |
应用公共测试标准(包括命名约定) | 可以共享代码或者测试的所有权,对测试达成共识 |
将测试(什么)和(如何)执行分隔 | 把什么(和为什么)抽象出来可以让各层分别完善;为使人读懂规则说明(测试),你可以增加更多示例,或者在不会影响精力规则的前提下更改底层自动化实现 |
依据 J.Timothy King 所总结的《测试先行的 12 个好处》:
详见:《测试驱动开发》
详见:《测试代码的坏味道》
测试代码坏味道,是指单元测试代码中的不良编程实践(例如,测试用例的组织方式,实现方式以及彼此之间的交互方式),它们表明测试源代码中潜在的设计问题。
常见的测试坏味道:
然后,再来个 Examples。
相关的工具:
前提条件:消费者和生产者都同意需要一个约束彼此交互的契约。当只有消费者愿意采用契约测试时,是很难进行契约测试的。
消费者驱动契约测试(Consumer-Driven Contracts Testing)背后的理念是定义每个服务消费者与提供者之间的契约,然后根据该契约对消费者和提供者进行独立测试,以验证他们是否符合契约约定的事项。
Resources: Qixi's presentations
Ant + JUnit + Jacoco 示例:model-ant-project
UI Recorder是一款零成本的整体自动化测试解决方案,一次自测等于多次测试,测一个浏览器等于测多个浏览器!
简单来说就是把你每次自测的流程录制下来,而且是全可视化的,然后在各种浏览器上自动回放。
F2etest 是一个面向前端、测试、产品等岗位的多浏览器兼容性测试整体解决方案。
Polly.JS 是一个独立于框架且与框架无关的J avaScript 库,可用于记录,重放和中断HTTP交互。 通过在Node和浏览器上利用多个请求 API,Polly.JS 能够在几乎没有配置的情况下模拟请求和响应,同时使您能够通过简单,强大且直观的 API 来完全控制每个请求。
TCPCopy是用来做TCP重放的,常用的场景是把线上流量复制到测试环境,用来排查线下不容易重现的问题,或者对测试环境做压力测试。
功能:
3.组成部分
goreplay是一款从生产环境copy流量到测试环境的工具,且不会影响生产环境的业务响应,又能很简单的达到复用http请求来做稳定性测试的目的。
GoReplay 工作方式:listener server 捕获流量,并将其发送至 replay server 或者保存至文件。replay server 会将流量转移至配置的地址。
最简单的使用模式是:listener server捕获流量,并将其发送至kafka,然后解析kafka的消息并存入mysql,处理起来还是比较方便的.
go-tcp-proxy A small TCP proxy written in Go. This project was intended for debugging text-based protocols. The next version will address binary protocols.
Go:https://github.com/jpillora/go-tcp-proxy, A small TCP proxy written in Go
对应的客户端示例:Java + Spring: SpringBoot TCP client/server Integration Example
Taurus是一个用于测试自动化的开源框架。 这个免费工具运行来自其他开源工具的脚本的性能测试,包括JMeter,Gatling,Locust和Selenium。 通过扩展他们的能力并掩盖复杂性,Taurus提供了一种创建,运行和分析负载测试的简单方法。 Taurus使用YAML或JSON,它们更容易管理。
官网:https://gettaurus.org/
┌───── 1 73 users, 2 ~73 active ─────┐┌──────────────────── Latest Interval Stats at 18:03:47 ────────────────────┐ ┌─┬─┐
│ ..o││ Average Times: Percentiles: Response Codes: │ │
│ .o..o││ Elapsed: 4.566 0.0%: 3.224 200: 100.00% (34)│ │ ┌───┐ ┬ ┬ ┬──┐ ┬ ┬ ┌───┐
│ o.oo.o..o││ Connect: 0.170 50.0%: 5.068 All: 100.00% (34)│ │ ┌───┤ │ │ │ │ │ └───┐
│ o.o.o.oo.oo.o││ Latency: 1.480 90.0%: 5.248 │ ┴ └───┴ └───┴ ┴ └───┴ └───┘
│ oo.o.o.o.oo.oooo││ 95.0%: 6.088 │ \ v1.14.2 by BlazeMeter.com \
│ oo.oo.o.o.o.oo.oooo││ 99.0%: 6.796 │
│ ooo.oo.oo.o.o.o.ooooooo││ 99.9%: 6.796 │JMeter: quick-test
│ .oooooooooooo.o.ooooooooooo││ 100.0%: 6.796 │ 15 %
│ .ooooooooooooooooooooooooooooo││ │Elapsed: 00:00:54 ETA: 00:05:05
│ ..oooooooooooooooooooooooooooooooo││ │
│oooooooooooooooooooooooooooooooooooo││ │ local
└────────────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘ disk-write: 8,334,038
┌──────── 1 34 hits, 2 0 fail ───────┐┌──────────────────────── Cumulative Stats 00:00:36 ────────────────────────┐ engine-loop: 0.154
│ . . . ││ Average Times: Percentiles: Response Codes: │ disk-read: 4,063,098
│ . . . . .││ Elapsed: 1.774 0.0%: 0.240 200: 100.00% (745)│ conn-all: 147
│ .. . . . . . .││ Connect: 0.074 50.0%: 1.553 All: 100.00% (745)│ bytes-recv: 1,454,890
│ . . .. .. . . . . . .││ Latency: 0.576 90.0%: 3.000 │ bytes-sent: 504,321
│ . . ....... .. .. . . . . . .││ 95.0%: 4.204 │ cpu: 9.400
│ . .......... .. .. . . . .. . .││ 99.0%: 5.388 │ disk-space: 86.600
│ ................. .. . . . .. .. .││ 99.9%: 6.796 │ mem: 64.200
│ ....................... . . .. .. .││ 100.0%: 6.796 │
│ ...................................││ │
│ ...................................││ │
│....................................││ │
└────────────────────────────────────┘│ │
┌─ 1 4.566 avg time (2 lat, 3 conn) ─┐│ Labels Hits Failures Avg Time │──────────────────────────────────────
│ . ││https://www.google.com/ 745 0.00% 1.774 │18:03:29 INFO: Changed data analysis
│ ..││ │delay to 3s
│ . ..││ Errors: │18:03:37 INFO: Changed data analysis
│ . ...││No failures occured │delay to 4s
│ ........││ │18:03:47 INFO: Changed data analysis
│ ..........││ │delay to 5s
│ .......o....││ │18:03:51 INFO: Changed data analysis
│ ..............o..oo││ │delay to 6s
│ . .................oo@oooo││ │18:03:57 INFO: Changed data analysis
│. ...............oooooooooooo@oo@o││ │delay to 8s
│@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@││ │18:04:01 INFO: Changed data analysis
└────────────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘delay to 9s
V 模型可以分为三部分,分析阶段、编码阶段、测试阶段。
V 模型开创性地提出 测试 的重要性,并且明确表明在不同的项目阶段,应完成对应级别的测试活动,强调每个测试活动与之对应分析活动的关联性,用户需求与验收测试关联、需求分析与系统测试关联、概要分析与集成测试关联、详细分析与单元测试关联。
双V模型也叫W模型,但是W并不能体现出开发与测试的分离与并行,甚至容易让人产生两个V模型串行执行的误会,所以笔者更倾向于 双V模型 。
X模型是对V模型的改进,X模型提出针对单独的程序片段进行相互分离的编码和测试。此后通过频繁的交接,通过集成最终合成为可执行的程序。
H模型将软件测试活动完全独立出来,始终贯穿于产品生命周期,与其他流程并发进行。当某个测试点准备就绪,就可以从测试准备阶段进行到测试执行阶段。软件测试可以尽早的进行,并且可以根据被测物的不同而分层次进行。
安全测试是确定信息系统是否保护数据免受恶意攻击的过程。为了完全测试软件安全性而需要设计的数据集必须涵盖以下主题:
在黑匣子测试中,测试人员看不到该代码。您的功能测试用例可以具有符合以下条件的测试数据:
Google 测试数据管理 实践:
GoReplay is an open-source network monitoring tool which can record your live traffic, and use it for shadowing, load testing, monitoring and detailed analysis.
# Run on servers where you want to catch traffic. You can run it on every `web` machine.
sudo gor --input-raw :80 --output-http http://staging.com
Flowgger is a fast, simple and lightweight data collector written in Rust.
Flowgger supports common input types: stdin, UDP, TCP, TLS and Redis, as well as multiple input formats: JSON (GELF), LTSV, Cap'n Proto and RFC5424. Normalized messages can be sent to Kafka, Graylog, to downstream Flowgger servers, or to other log collectors for further processing.
Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in your persistence to stress test it, or anonymize data taken from a production service, Faker is for you.
from faker import Faker
fake = Faker()
fake.name()
# 'Lucy Cechtelar'
fake.address()
# '426 Jordy Lodge
# Cartwrightshire, SC 88120-6700'
fake.text()
# 'Sint velit eveniet. Rerum atque repellat voluptatem quia rerum. Numquam excepturi
# beatae sint laudantium consequatur. Magni occaecati itaque sint et sit tempore. Nesciunt
# amet quidem. Iusto deleniti cum autem ad quia aperiam.
Datafaker 是一个大批量测试数据和流测试数据生成工具,兼容 Python2.7 和 Python3.4+。
文章来源:《【架构拾集】移动应用的自动化测试(BDD 方式)》
作为一个团队的技术负责人,我希望:拥有一个移动应用测试架构,它能快速让测试人员快速上手——阅读、编写测试用例。与此同时,我希望这些测试用例是能让非技术人员阅读,诸如业务分析人员,并且符合真实的用户使用场景。
当我们谈到业务分析人员也能编写的测试,我们说的只有 BDD(Behavior Driven Development,行为驱动开发)。它是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA(测试人员)和非技术人员或商业参与者之间的协作。
BDD 在这一种上相当的迷人——能让非技术人员编写测试。而其核心的部分在于:创建了一个环境隔离的 DSL,仿人类语言的 DSL。咳咳,这个 DSL 实现起来,可不轻松。关注顶层 DSL 的同时,开发人员还要努力实现好底层的实现。举个简单的例子,如下是之前在 BDD 一文中的 DSL 示例,这是顶层的设计:
功能: 失败的登录
场景大纲: 失败的登录
假设 当我在网站的首页
对应的,开发人员需要编写实现:
Given('当我在网站的首页', function () {
return this.driver.get('http://0.0.0.0:7272/');
});
从上述的代码中,一眼就可以看出复杂的地方,实现一个领域特定(业务特定)的 DSL 语言。
我们要完成的 DSL 实现,上层是提供一个 DSL,下层则是对接 driver 的 Agent 层。在 Web 领域里,这个 driver 的 Agent 层负责对接不同的浏览器,诸如 Selenium,driver 则视不同的浏览器而有所不同,如 ChromeDriver、FirefoxDriver、PhantomJSDriver 等等。Selenium 这样的测试框架,除了通过 driver 直接操作了浏览器,还提供了不同语言的编程接口。
相似的,在 APP 领域也有这样的方案,它要通常这个 agent 来连接物理设备,并提供一系列的编程接口。
对整个架构有了一个基本的认识之后,让我们继续往下移动,来重新发掘一下:我们究竟需要哪些基本元素?
从这一点上来看,它与 Web 应用的 BDD 架构差不多。为此,我们需要准备如下的一些框架:
由于我们计划的顶层是由 DSL 来实现,而对应的 BDD 层实现是由 Robot Framework 来完成的。Robot Framework 使用的是 Python 语言,我们就需要找到对应的 Python 主要依赖有:
有了这些主要的库,我们就可以编写我们的 DSL?不,我们还需要配置好,对应的移动端 Driver。
Android Driver 依赖
比较简单,通过 appium-uiautomator2-driver
库就拥有了 driver。
iOS Driver 依赖
为了实现对 iOS 设备的自动化测试,需要安装 XCUITest,为此我们需要下面的这一系列工具:
libimobiledevice
,是一个跨平台的用于与 iOS 设备通讯的协议库,它可以让 Windows、macOS、GNU/Linux 系统连接 iPhone/iPod Touch 等 iOS 设备。carthage
是一个简单的、去中心化的依赖管理工具。ios-deploy
是一个使用命令行安装 iOS 应用程序到连接设备的工具xcodebuild
,是苹果发布自动构建的工具。xcpretty
,用于对 xcodebuild 的输出进行格式化,包含输出 report 功能。看,有了这一系列的知识,我们几乎知道怎么做搭建移动应用的自动化测试。