专注测试技术的课程订阅站点

QA Leader的职责是什么

很少看到有人讨论 qa leader 的职责,最近正好看到一篇,随手翻译了一下,供大家参考。

在这篇文章中,我将分享我作为测试负责人的经验。

负责人可以是测试负责人、QA 负责人、测试负责人,等等。

虽然职位名称可能不同,但我负责领导一个测试团队。

根据我大约 20 年的经验,我列出了负责人 QA 工程师的任务。

负责人扮演着双重角色。

他/她既是实际参与者,也是管理者。

实际参与者意味着他编写测试用例,运行它们,报告错误,进行缺陷审查等等。

这些任务都是由个人贡献者完成的。对吧?

除此之外,负责人还承担其他任务。

这比个人贡献者更多。他/她是产品/项目的其他利益相关者眼中的团队代表。

现在,让我们详细了解这些任务。

作为个人贡献者的活动

QA 负责人的主要任务是测试。

也就是实际参与者。通常,负责人的工作分配大约是 70-30%的时间。

也就是 70%作为个人测试人员,30%作为负责人的活动。

这可能因项目而异。

好了,现在作为手动测试人员,负责人会做以下工作:

  • 实际测试
  • 编写测试用例,
  • 执行测试用例。
  • 编写自动化脚本,
  • 审查测试用例/自动化代码
  • 执行脚本
  • 提 bug
  • 文档编写

你可能会说这些都是由每个团队成员完成的。对吧?

作为负责人的活动

现在,让我们看看负责人特定的任务。

我还列出了负责人的责任。

  • 分配任务。
  • 进行工作量估计。
  • 对测试负责。
  • 通过支持他们来保护测试人员。
  • 对估算的任何延误负责。
  • 确保分配的任务完成。
  • 有点像夹心饼干 - 位于管理层和团队之间!
  • 准备不同的文档,如测试策略、测试计划。
  • 还准备测试报告、状态报告。
  • 与开发、IT、产品、客户支持团队进行沟通。
  • 帮助招聘和建立自己团队以及其他团队。
  • 在公司和客户层面为测试工具/项目或自动化开展多个概念验证(POC)。
  • 培训初级人员。
  • 在需要专家知识的其他项目中做出贡献,或者只是帮助他们进行指导/审查他们的自动化。因此,这是负责人提供的额外咨询服务。
  • 在其他人不计划休假时支持团队交付工作。也就是说,当需要时,负责人(他/她)会介入并执行任务。
  • 寻找改进测试流程的方法,并为团队创造心理安全环境,使他们能够做出最好的工作。
  • 发布计划和估算。在发布计划和估算中发表意见是 QA 负责人的主要技能和责任。
  • 与支持团队一起解决生产问题。
  • 例如,重现问题,确定延误的根本原因等等。
  • 设计/增强自动化框架

总而言之,QA 负责人领导、指导和监控测试分析、设计、实施和执行,测试程序和测试套件。

常用的adb命令

Android Debug Bridge 是我们比较常用的命令行工具,该工具可以在 Android 设备上执行不同的操作,例如安装或卸载应用程序、输入文本、捕获屏幕截图等,下面是一些常用的 adb 命令及使用场景。

**列出连接的设备**

adb devices

上面的命令可以列出设备的序列号和状态,如果连接了许多设备并且我们想将它们区分开来,我们可以运行带有-l选项的命令以列出有关设备的更多详细信息。

adb devices -l

此命令向我们显示设备、型号等。

**安装应用程序**

通过提供.apk文件的路径,可以在设备上安装应用程序

adb install <path_to_apk>.apk

如果连接了多个设备,直接运行上面的命令是会报错的,这时应使用-s选项指定目标设备的序列号。

adb -s <serial_number> install <path_to_apk>.apk

这里的-s是一个常用选项,用于指定具体的设备,会在 adb 命令中大量使用到。

**列出 package**

adb shell 中的包管理器(package manager)工具可用于列出设备上安装的所有包

adb shell pm list packages

后面接grep命令可以实现更为精确的过滤

adb shell pm list package | grep what_you_want

启动**Activity**

可以用下面的命令来找到指定的 package 中的某个 activity

adb shell dumpsys package | grep <package_name> | grep Activity

然后下面的命令可以启动 activity

adb shell am start <package_name>/<activity_name>

比如下面的命令可以启动 google map

亲历裁员竞赛

今年的年度关键词里大概率会出现裁员这个选项。国内互联网公司风风火火的进行了一整年,最近硅谷也在跟进,根据已经放出风来的口径统计的话,硅谷头部公司大概会裁员 120k 左右,超过了当年互联网泡沫时期的 107k,有分析人士指出,这只是开始而已,这个冬天,裁员的寒风会更加凛冽。

裁员的逻辑

逻辑其实很简单,全球经济不好,互联网增长不及预期,而且找不到新的增长点,这样之前为增长而储备的人力就需要释放,裁员明显是一个很好的选项,所以华尔街出现了一些公司越裁员股价越涨的情况。另外一般以增长为目标的项目或产品,往往投入高收益少,也就是所谓不赚钱的业务,后面裁员的目标将非常聚焦和具体,只要不赚钱,那么走人的可能性就非常大。

被裁之后

首先被裁不是员工自身的问题,所谓的时势造英雄,整个大环境不好让所有人都很难独善其身。被裁之后的心理压力一定是巨大的,管理好情绪开始下一段旅程,这个世界还是充满着无限的可能,不要因为别人的错误而自怨自艾,记住,在这个大的时代背景和叙事框架下,你的被裁大概率是在为别人的失误买单。

风暴中心

这次我其实处在裁员的风暴中心,分享几个事情。

我们部门这次裁员了 75%,之前坐满了一层楼,而且裁员两天后就已经冷冷清清,士气凋零。

跟同事聊天,他说有些毕业生被裁后拿到的赔偿金额够他们生活 1 到 2 年,完全有时间去考公上岸,也算是提前离场,开启下一段人生。

其他部门很多同事人心惶惶,下一个是不是自己无法确定,下一波什么时候到来也让人惴惴不安。

跟国外的同事聊天,他们目前有 11 个人,下个月就只有 10 个人,因为其中 1 人收到了 np,notice period,有兴趣的同学可以查查是什么意思。他们国家今年经济其实发展的不错,但是互联网行业整体不行,其他大厂也在裁员,相当惨烈。安慰了他几句,很默契的互相留了联系方式,因为大家都不知道哪天会突然离开。

配合另一地区的同事进行上线之前的验收,那位同学早上还在提 bug,下午的时候就忽然告诉我他要走了,刚刚被裁,last day 就是今天下班。我无话可说,安慰了几句,互相留了联系方式。感觉像是在玩狼人杀,每天都有人被刀的样子,期待明天会是一个平安夜。他走的时候问我:你觉得今年会不会有年终奖?我的回答是: I doubt。

有的人被裁后很快就找到了工作,也有的人两个月了没什么进展,找工作这个事情因人而异,但总体看来市场上的需求明显不如几年前那么旺盛。

有人觉得压抑,想主动离开,我总是劝留不劝走,从行业内来看,外面的世界无奈大过于精彩。

经常有滚动裁员,量不大,比如前两天又离开了 10%左右,工作的安全感非常欠缺。

总结

其实无话可说,安全第一,共克时艰。

用python实现简单的版本号生成工具

我们发布比较频繁,每次发布都需要从 release 分支打 1 个 tag,不过可能是因为年纪大了的缘故吧,尽管借鉴了一些版本号的制定规则,不过每次我都记不太住,需要翻文档去重新复习,不如把这步自动化一下,为未来的自己节约一点时间,另外有了工具就好统一规则,后面所有相关的项目都可以用同一套规则来生成版本号,去掉了人工对齐的成本,变相提升了效率。

版本号规则

我们的版本号大概长这个样子

v1.00.0-hotfix-20221111-1
版本号   发布类型 发布时间  第几次发布
  • 版本号规则: 大版本 1 位 + 小版本 2 位 + patch 版本号 1,比如 v1.00.0 表示大版本是 1,小版本是 0,patch 版本是 0
  • 发布类型:普通发布/hotfix/adhoc(临时版本)

设计

首先不考虑写页面做系统,其实用 vue 随便写个单页应用是可以很快搞定的,不过没那个必要,用命令行工具就好了,简单快速,而且生成了版本号之后可以调用 githlab(我们公司用私有化部署的版本)api 来自动打 tag,在微服务化当道的今天,手动为每次发布的所有 repo 打版本号本身就不是一个很好的体验。命令行工具在这方面比单页应用更具优势一些。

另外交互式的命令行可以省去很多参数 validation 的工作量,这也应该是考虑的。随便搜索了一下,发现了 1 个名为 inquirer 的库可以很好的满足我的需求。

代码实现

import inquirer
from datetime import datetime

STR_MAP = {
	'regular': '',
	'hotfix': '-hotfix',
	'adhoc': '-adhoc'
}

def build_version(options):
	release_type = STR_MAP[options['release_type'][0]]
	date = datetime.now().strftime('%Y%m%d')
	return f"v{options['version']}{release_type}-{date}-{options['seq']}"

if __name__ == "__main__":

	questions = [
		inquirer.Text("version", message="Please enter a version, for sample 1.00.0", default='2.00.0'),
		inquirer.Checkbox(
			"release_type",
			message="Please select a release type",
			choices=["regular", "hotfix", "adhoc"],
			default=['regular']
		),
		inquirer.Text("seq", message="please enter the sequence", default='1'),
		inquirer.Confirm(
			"correct",
			message="This will generate a tag name. Continue?",
			default=False,
		),
	]
	answers = inquirer.prompt(questions)

	if answers['correct']:
		tag_name = build_version(answers)
		print(tag_name)
	else:
		print('nothing to do')

整体流程非常的简单

python requests的替代者?httpx初体验

python 的 requests 库由于其使用简单,文档丰富成为了很多人在发送 http 请求时候的优选选择。前几天看到了一个类似的实现 httpx,在这里简单使用体验一下,顺便简单分享一下体验心得。

相比较 requests,httpx 支持 sync 和 async 的 API,支持 http1.1 和 http2。httpx 尽最大努力兼容 requests 的 API,这样一来用户从 requests 转换到 httpx 的成本就相对较为低廉了。

基本 API

>>> import httpx
>>> r = httpx.get('https://www.example.org/')
>>> r
<Response [200 OK]>
>>> r.status_code
200
>>> r.headers['content-type']
'text/html; charset=UTF-8'
>>> r.text
'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'

简单扫一圈,满眼都是 requests 当年的样子。下面是 requests 的 API,大家来找茬,看看哪里不一样。

>>> import requests
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>> r.status_code
200
>> r.headers['content-type']
'application/json; charset=utf8'
>> r.encoding
'utf-8'
>> r.text
'{"type":"User"...'
>> r.json()
{'private_gists': 419, 'total_private_repos': 77, ...}

不能说非常相似,只能说是一模一样。

httpx client

requests 为一组 http 请求提供了 session 对象来进行统一设置和管理,httpx 则相应的提供了 client 对象。我们来对比一下使用方式先。

如何优化selenium webdriver的执行速度

让自动化测试脚本正常工作只是自动化测试的第一步,由于自动化脚本会经常执行并更新,因此测试脚本需要

  • 可以快速执行
  • 容易维护
  • 容易阅读

本文会提供一些让 selenium 自动化脚本运行的更快的技巧。

在 page_source 中断言 text 比直接使用 text 属性断言要快

我们经常会需要断言页面中的某个部分包含一些具体的文本,下面的语句的输出结果是相同的

driver.page_source
driver.find_element(:tag_name => body') .

不过对于第二条语句来说,selenium 需要去分析页面的结构,最后再找到对应的元素并输入结果,这显然是需要花费时间的。如果页面比较小的化,那么二者的差距可能不大,不过对于大的页面来说,第一条语句速度明显会更快一些。

使用 page text 的情况

expect(driver.find_element(:tag_name => "body").text).to include("platform- and language-neutral wire protocol")

使用 page source 的情况

expect(driver.page_source).to include("platform- and language-neutral wire protocol")

来看一下差距

Method 1: Search whole document text took 0.823076 seconds
Method 2: Search whole document HTML took 0.039573 seconds

当然两者的使用场景是不太相同的,不过我们这里只关注性能,显然 page source 要更快速一些。

元素越具体,获取 text 的速度越快

根据经验,我们可以通过缩小更具体的 Web 控件的范围来节省执行时间。下面的两个断言语句在很大程度上实现了相同的功能,但在执行时间上有很大的不同。

expect(driver.find_element(:tag_name, body).text).to include(language-neutral wire)

这条语句的执行时间是 0.93s

expect(driver.find_element(:id, abstract).text).to include(language-neutral wire)

这个断言只执行了 0.02s

很明显,第 2 个断言除了在执行速度上更快之外,断言也更加精确,更容易理解。

使用变量去缓存没有变化的元素

我经常看到有人编写如下测试来检查页面上的多个文本。

driver.navigate.to(site_url + "/WebDriverStandard.html") expect(driver.find_element(:tag_name, "body").text).to include("Firefox")
expect(driver.find_element(:tag_name, "body") ").text).to include("chrome")
expect(driver.find_element(:tag_name, "body").text).to include("W3C")

执行时间 2.35s

上述三个测试语句非常低效,因为每个测试语句都调用driver.find_element(:tag_name, 'body').text,当网页很大时,这可能是费时费力的工作。