最常见的解释是:软件测试就是找 BUG,发现缺陷。
生活中有着诸多事情,我们都在默默地测试:
新买来的一部手机,我们要 “测试” 它的功能;
自己组装一台电脑,喜欢用跑分软件 “测试” ;
等等…
软件测试,就是验证软件产品特性是否满足用户的需求。
早期,人们更多的将测试看成对软件产品的 “检验”,检查软件的每个功能是否运行正常。
- 难易程度:开发广度小,专业度高。测试广度大,专业度低。
- 工作环境:基本一致。
- 薪资:中小型企业比开发低。大厂研发测试基本无差别。
- 发展前景:自动化测试、安全测试等领域发展前景和研发基本一致。
- 繁忙程度:敏捷模式下差距不大,产品发布前压力比较大。
- 技能要求:测试要求更广泛:业务能力,设计和架构分析能力,测试手段和工具使用,用户模型分析和理解,编程能力。
1. 目的不同
调试:发现并解决软件中的缺陷。
测试:发现软件中的缺陷。
2. 参与角色不同
调试:开发人员。
测试:测试人员,开发人员等。
3. 执行的阶段不同
调试:编码阶段。
测试:测试贯穿软件的整个生命周期。
1. 综合能力
2. 掌握自动化测试技术
掌握自动化测试技术,可以解法大量重复性的手工劳动测试,这样可以把更多的精力花在更多类型的测试上。
3. 优秀的测试用例设计能力
测试用例设计能力是指,无论什么类型测试,都能设计出高效地发现缺陷,保证产品质量的优秀测试用例。
掌握设计测试用例的方法;积累和总结测试用例;阅读好的测试用例设计方案。
4. 探索性思维
探索性思维是指,测试工程师在执行测试的过程中不断学习,结合自己的经验,知识,直觉进行系统的错误猜测和逻辑推理,整理分析出更多针对性的测试关注点。
5. 兴趣
学习和工作,有无兴趣都很重要。
6. 有责任感和一定的压力
测试往往是产品质量的最后把关者;由于测试工作成效很难衡量,测试用例执行、bug 数目的多少都无法说明产品的质量是否合格;所以,责任感是最重要的测试必备素质之一。
如何事务都会有纰漏,出现纰漏要抗住压力,总结经验避免后续再次出现类似问题。
衡量软件测试结果的依据。
需求的概念
满足用户期望或正式规定文档(合同、标准、规范)所具有的条件和权能,包含用户需求和软件需求。
大多数软件公司,会有两部分需求,一部分是用户需求,一部分是软件需求。
用户需求:可以简单理解为甲方提出的需求,如果没有甲方,那么就是终端用户使用产品时必须要完成的任务。该需求一般比较简略。
软件需求:或者叫功能需求,该需求会详细描述开发人员必须实现的软件功能。
在进行软件开发的时候,会把用户需求转化为软件需求,开发人员和测试人员工作的直接依据就是软件需求。
软件需求是测试人员进行测试工作的基本依据。
软件需求规格说明书
一、用户需求:
平台支持邮箱注册
二、软件需求:
1.1.1.1 注册账号
1.1.1.1.1 功能概述
用户可以通过填写邮箱信息在平台注册个人用户。
1.1.1.1.2 用户角色
匿名用户。
1.1.1.1.3 前置条件
无。
1.1.1.1.4 输入
| **序号** | **栏位名称** | **栏位说明** | **长度** | **类型** | **备注**
|
| --- | ---------- | ------------------- | ------- | ------ | ------ |
| 1 | 姓名 | 必填,录入个人姓名 | 6至15 | 字符型 |
|
| 2 | 电子邮箱 | 必填,录入电子邮箱 | | 字符型 |
|
| 3 | 密码 | 必输,输入的密码隐藏*号显示,最短6位 | 6至15 | 字符型 |
|
| 4 | 确认密码 | 必输,输入的密码隐藏*号显示,最短6位 | 6至15 | 字符型 | |
| 5 | 验证码 | 必填,录入验证码 | | 字符型 |
|
| 6 | 注册 | 注册操作 | | 操作型 |
1.1.1.1.5 处理
1.1.1.1.5.1 基本事件流
1、 用户选择注册;
2、 系统展现用户协议界面,并请用户确认是否同意用户协议
1) 若用户不同意协议,系统禁止用户注册。
2) 若用户同意协议,用户进行注册信息填写。
3、 用户填写注册信息。
注册个人,填写:姓名,电子邮箱,密码,确认密码,验证码。
4、 用户提交注册信息;
5、 系统提示用户并向用户注册的电子邮件地址发送一封含有激活信息的电子邮件。系统并提示用户,若未收
到激活邮件,可使用注册的邮箱和密码登录系统后再次发送激活邮件。
6、 用户可执行激活操作,直接跳转至注册邮箱门户页面。
7、 用户通过接收到的电子邮件中的激活信息激活账号,用户注册完成,流程结束。
1.1.1.1.5.2 扩展事件流
1. 用户注册并激活成功后,第一次登录平台时,提示用户完善信息;
1.1.1.1.5.3 异常事件流
1. 若用户未收到激活邮件,可在登录界面录入电子邮件及密码后,再次发送激活邮件。
2. 每次发送的激活邮件,仅在发送邮件后起24小时之内有效,超过24小时后需重新发送激活邮件。
1.1.1.1.6 输出
用户注册成功
1.1.1.1.7 后置条件
该模块为用户登陆等的前置模块。
需求是测试人员开展软件测试工作的依据。
在具体设计测试用例的时候,首先要搞清楚每个业务需求对应的多个软件功能需求点,然后分析出每个软件功能需求点对应的多个测试需求点,最后针对每个测试需求点设计测试用例。
过程如下:
业务需求 -> 软件功能需求点 -> 测试需求点 -> 测试用例。
以 “用户登录” 为例:

为什么需求对软件测试人员如此重要
如何才能深入理解被测试软件的需求
测试工程师在需求分析和设计阶段就可以开始介入,这个阶段是理解和掌握软件的原始业务需求的最好时机。
只有真正的理解了原始业务需求之后,才能从业务需求的角度去设计具有针对性的,覆盖率较高的测试用例集。
测试用例(Test Case)是为了实施测试而向被测试的系统提供的一组集合,这组集合包含:测试环境、操作步骤、测试数据、预期结果等要素。
测试用例解决了两大问题:测什么,怎么测。
案例一:
测试用例 ecsp-439:用户注册成功
| 步骤操作 | 期望结果 |
|---|---|
| 进入注册页面,选择注册 | 系统展现注册页面 |
| 输入符合要求的信息用户名、邮箱、密码、验证码等,并确认同意用户注册协议,提交注册信息 | 系统进行注册,发送激活邮件。发送成功后,跳转到注册成功页面,并提示用户进行邮箱激活 |
| 进入邮箱,进行激活操作 | 激活成功 |
| 使用注册的邮箱和密码,进行登录操作 | 登录成功,系统展示欢迎页面 |
| 测试方式 | 手工 |
| 重要性 | 重要 |
| 测试环境 | CHROME, IE 10+ |
| 测试前提 | 系统运行正常,邮件服务器已启动 |
| 功能模块 | 注册登录 |
案例二:
注册网易邮箱。

标题:注册网易邮箱
测试环境:win10、chrome 版本 103.1.5060.66(正式版本)(64位)
测试数据:
邮箱地址:111222333
密码:123456
手机号:10086111
验证码:s9g8
测试步骤:
1. 打开谷歌浏览器,输入网易注册网址:https://mail.163.com/register/index.htm?from=163mail&utm_source=163mail
2. 输入邮箱地址、密码、手机号、获取验证码并输入验证码,勾选用户协议。
3. 点击注册。
期望结果:
展现注册成功的结果页面,并且使用账号可以成功登录。
测试过程中可能会遇到下列问题:
测试用例的存在就是为了解决上述问题,同时测试用例也要避免用后即弃!
第一个 bug 的故事
1945年9月的某天,在一间老式建筑里,从窗外飞进来一只飞蛾,此时Hopper正埋头工作在一台名为Mark Il的计算机前,并没有注意到这只即将造就历史事件的飞蛾。这台计算机使用了大量的继电器(电子机械装置,那时还没有使用晶体管)。突然,Mark II死机了。Hopper试了很多次还是不能启动,他开始用各种方法查找问题,最后定位到了某个电路板的继电器上。Hopper观察这个继电器,惊奇地发现一只飞蛾已经被继电器打死。Hopper小心地用镊子将飞蛾夹出来,用透明胶布贴到“事件记录本”中,写上“第一个发现虫子的实例”。Hopper的事件记录本,连同那只飞蛾,现在都陈列在美国历史博物馆中。软件错误的一般定义: 程序与规格说明之前不匹配 。
注意:以上说法是片面的,准确的来说:当且仅当规格说明是存在的并且正确,程序与规格说明之间的不匹配才是错误。
当需求规格说明书没有提到的功能,判断标准以最终用户为准:当程序没有实现其最终用户合理预期的功能需求时,就是软件错误。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput