众所周知,头部互联网公司测试团队已经逐渐由人海战术过渡到精干单体作战阶段,测试人员与开发人员的比例已经由1:1逐渐过渡到1:12甚至更多,而产品质量也是步步高升。
在测试人员精简的前提下,他们是如何做到的呢?
秘诀有很多,最关键的有两点,工具和人员。今天就暂且抛开各种辅助提效工具,重点说一下测试人员素质的提升。
传统意义上的测试人员无非关注以下几点:
-
良好的业务理解能力
-
良好的沟通表达能力
-
一定的抗压能力
-
最基础的技术能力
具备以上素质,基本可以胜任大部分公司的业务功能测试了。但是随着业务迭代的加速,由于测试人员不能根据具体变动分析到位,在资源有限的条件下,只能是局部重点无脑覆盖,至于是否命中以及命中了多少,只能根据经验粗略估算。如果要追求一个较高的场景覆盖,那只能增加资源的投入。一是人力的增加,而这明显与前面提到的比例趋势背道而驰;二是单人工作时长的延长,但这个明显只能偶尔为之,不可持续。
那正确的做法是什么呢?
提升人员素质,提高单兵作战能力。不仅需要在测试方面精益求精,还需要深入了解开发的技巧。而这方面的提升,可以保证测试人员清楚洞察开发的架构设计与代码实现,进而针对实际变更,从整体和局部两方面入手,合理设计测试用例,并编写针对的脚本,进而提高单位时间的覆盖率,从而保证质量的一致性。
现在手头有这么一个需求,某项服务的IP地址需要进行变更,而该项服务IP地址是通过配置中心的某个值设定的,要求在变更后保证服务的可用性。
那对于测试人员需要如何入手呢?
首要问题是需要评估通过修改配置中心的对应IP地址,是否需要重启服务才能生效。对于传统人员来说,可能会先执行一遍测试用例,发现实际结果与预期结果不一致,才能推断出需要重新启动该项服务。
那正确的做法呢?
可以从该配置项生效的地方入手。如下文所示,实例是定义在单例模式中:
public static synchronized XXXClientFactory getInstance(address){
if (instance !=null){
return instance;
}else
{
instance = new XXXClientFactory(address);
}
}
很明显该方法是静态方法,由此我们可以得出该实例仅仅会初始化一次。如果直接进行配置中心相关配置项的变更,IP变更并不会生效,所以我们应该在变更地址后,果断重启服务,这样前面的试错就可以避免了,效率自然而然就提高了。由此可见,了解单例模式对于测试人员还是很有帮助的。
接下来就让我们从简单的单例模式的学习开始吧。Java单例模式有如下5种实现方式。
1、饱汉模式——非线程安全
public class Singleton1 {
private static Singleton1 singleton = null;
private Singleton1() {
}
public static Singleton1 getInstance() {
if (singleton == null) {
singleton = new Singleton1();
}
return singleton;
}
}
该种模式的优点是懒加载,启动快,资源占用小,使用时才实例化,无锁,缺点是非线程安全。
2、饱汉模式——线程安全
public class Singleton {
/**
* 定义一个变量来存储创建好的类实例
*/
private static Singleton uniqueInstance = null;
/**
* 私有化构造方法,好在内部控制创建实例的数目
*/
private Singleton(){
}
/**
* 定义一个方法来为客户端提供类实例
* @return 一个Singleton的实例
*/
public static synchronized Singleton getInstance(){
//判断存储实例的变量是否有值
if(uniqueInstance == null){
//如果没有,就创建一个类实例,并把值赋值给存储类实例的变量
uniqueInstance = new Singleton();
}
//如果有值,那就直接使用
return uniqueInstance;
}
/**
* 示意方法,单例可以有自己的操作
*/
public void singletonOperation(){
//功能处理
}
/**
* 示意属性,单例可以有自己的属性
*/
private String singletonData;
/**
* 示意方法,让外部通过这些方法来访问属性的值
* @return 属性的值
*/
public String getSingletonData(){
return singletonData;
}
}
该模式优点同上,并且加了锁,缺点是synchronized 为独占排他锁,并发性能差。即使在创建成功以后,获取实例仍然是串行化操作。
3、饱汉模式——双重加锁检查
public class Singleton {
/**
* 对保存实例的变量添加volatile的修饰
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(Singleton.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
该模式是懒加载,线程安全。
4、饿汉模式
public class Singleton {
//定义一个静态变量来存储创建好的类实例
//直接在这里创建类实例,只会创建一次
private static Singleton instance = new Singleton();
//私有化构造方法,好在内部控制创建实例的数目
private Singleton(){
}
//定义一个方法来为客户端提供类实例
//这个方法需要定义成类方法,也就是要加static
//这个方法里面就不需要控制代码了
public static Singleton getInstance(){
//直接使用已经创建好的实例
return instance;
}
}
该模式优点是天生是线程安全的,使用时没有延迟,缺点是启动时即创建实例,启动慢,有可能造成资源浪费。
5、Holder模式
public class Singleton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
/**
* 私有化构造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
该模式将懒加载和线程安全完美结合的一种方式(无锁)。(推荐)
以上关于行业内人员变化趋势的一点个人思考和单例模式的介绍,希望能够对你有所帮助。
其他文章可以关注微信公众号测试架构师养成记,还有资料可以领哦~