1.本发明涉及计算机技术领域,尤其涉及一种软件测试方法、电子设备及存储介质。
背景技术:2.随着计算机技术的发展,越来越多的技术,例如,区块链(blockchain)、大数据、分布式等技术被应用在金融领域,传统金融业正在逐步向金融科技转变,然而,由于金融行业的安全性、实时性要求,金融科技也对技术提出了更高的要求。在金融科技领域下,在进行软件测试的过程中,当需要排除一些外部因素的干扰时,通常利用mock技术创建虚拟的mock对象,来替代不容易构造或不容易获得的对象进行测试。
3.相关技术中,通过修改被测源码中的java方法的字节码,构造出mock对象,并对被测源码完成测试之后,将修改的java方法恢复为原样。但构造mock对象涉及的mock语法较复杂,构造mock对象的效率较低且容易出错,导致软件测试效率较低。
技术实现要素:4.有鉴于此,本发明实施例提供一种软件测试方法、电子设备及存储介质,以解决相关技术中构造mock对象的效率较低且容易出错的技术问题。
5.为达到上述目的,本发明的技术方案是这样实现的:
6.本技术实施例提供了一种软件测试方法,应用于第一设备,所述方法包括:
7.在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同;
8.在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;
9.在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活;其中,
10.第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
11.上述方案中,每个mock方法还包括关于mock方法的第一注解;在所述激活所述第一测试用例相关的所有mock方法之前,所述方法还包括:
12.基于第一测试用例的源码中包括的第一注解,识别出第一测试用例相关的mock方法;
13.基于识别出的mock方法的第一注解和第一声明,从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法;基于确定出的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令;其中,所述第一指令用于指示第二设备在第一源码文件中的对应第一java方法中增加第一字节码。
14.上述方案中,所述识别出第一测试用例相关的mock方法,包括以下至少之一:
15.解析出第一测试用例所属的测试类,以及基于预先缓存的测试类和mock方法之间的对应关系,确定出第一测试用例相关的第一类mock方法;第一类mock方法的访问控制符为private;
16.基于第一测试用例的源码中包括的第二注解,确定出第一测试用例相关的第二类mock方法;其中,第二注解表征第一测试用例引用的一组公共的mock方法;第二类mock方法的访问控制符为public。
17.上述方案中,在所述从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法时,所述方法包括:
18.将第一mock方法的第一注解中的java类、第一mock方法的第一声明包括的第一函数的函数名和第一函数相关的每个参数的数据类型,按照设定方式进行排列,得到第一标识;
19.将java方法的第二声明包括的第二函数的函数名、第二函数的每个参数的数据类型,以及第二函数所属的java类,按照所述设定方式进行排列,得到第二标识;
20.在第一标识和第二标识相同的情况下,将对应的java方法确定为对应的第一mock方法对应的第一java方法。
21.所述mock方法包括以下至少之一:
22.公共方法;
23.私有方法;
24.公共静态方法;
25.私有静态方法;
26.包含修饰符final的方法。
27.本技术实施例还提供了一种软件测试方法,应用于第二设备,所述方法包括:
28.接收第一设备在执行第一测试用例的过程中发送的第一测试指令;其中,所述第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试;
29.在调用第一java方法进行测试之前,执行对应的第一字节码,以反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
30.上述方案中,所述执行所述第一字节码,包括:
31.在所述第一java方法对应的mock方法处于激活状态的情况下,通过反射调用所述第一java方法对应的mock方法,执行所述第一java方法对应的mock方法相关的指令;或者
32.在所述第一java方法对应的mock方法处于未激活状态的情况下,调用所述第一java方法进行测试。
33.本技术实施例还提供了一种电子设备,包括:
34.激活单元,用于在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同;
35.测试单元,用于在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;
36.卸载单元,用于在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活;其中,
37.第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试。
38.本技术实施例还提供了一种电子设备,包括:
39.接收单元,用于接收第一设备在执行第一测试用例的过程中发送的第一测试指令;其中,所述第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试;
40.测试单元,用于在调用所述第一java方法进行测试之前,执行所述第一字节码,以反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
41.本技术实施例还提供了一种电子设备,包括:处理器和用于存储能够在处理器上运行的计算机程序的存储器,
42.其中,所述处理器用于运行所述计算机程序时,执行上述应用于第一设备或第二设备的软件测试方法的步骤。
43.本技术实施例还提供了一种存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现上述应用于第一设备或第二设备的软件测试方法的步骤。
44.在本技术实施例中,在利用mock技术进行软件测试时,在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活。其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同;第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试。本方案中,测试用例中的mock方法是按照java的语法习惯构造出的,测试用例中的mock方法包括的声明与java方法的声明相同,在构造mock方法时,将原java方法的业务逻辑替换为mock方法的测试逻辑即可,由此,可以简化构造mock方法的语法,提高构造mock方法的效率较和降低构造出的mock方法存在语法错误的概率,进而提高测试效率。
附图说明
45.图1为本技术实施例提供的软件测试方法的交互图;
46.图2为本技术实施例提供的软件测试方法中增加第一字节码的交互图;
47.图3为本技术实施例提供的在java方法中增加第一字节码的示意图;
48.图4为本技术实施例提供的第一字节码对应的处理逻辑的示意图;
49.图5为本技术应用实施例提供的软件测试方法的交互图;
50.图6为本技术实施例提供的初始化流程的示意图;
51.图7为本技术实施例提供的一种电子设备的结构示意图;
52.图8为本技术另一实施例提供的一种电子设备的结构示意图;
53.图9为本技术实施例提供的一种电子设备的硬件组成结构示意图。
具体实施方式
54.相关技术中,在构建mock对象时,需要指定mock的目标对象,指定包含有目标对象的测试对象,以及定义相关的mock等,涉及的语法非常复杂,且与java的语法习惯差异大,开发人员的学习门槛非常高,这样一来,构造mock对象的效率较低且容易出错,软件测试效率较低。
55.基于此,本技术提供了一种软件测试方法,在利用mock技术进行软件测试时,在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活。其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同;第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试。本方案中,测试用例中的mock方法是按照java的语法习惯构造出的,测试用例中的mock方法包括的声明与java方法的声明相同,在构造mock方法时,将原java方法的业务逻辑替换为mock方法的测试逻辑即可,由此,可以简化构造mock方法的语法,提高构造mock方法的效率较和降低构造出的mock方法存在语法错误的概率,进而提高测试效率。
56.为了使本技术的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本技术进行进一步详细说明。应当理解,此处描述的具体实施例仅仅用以解释本技术,并不用于限定本技术。
57.图1为本技术实施例提供的软件测试方法的交互图。如图1示出的,软件测试方法包括:
58.步骤101:第一设备在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同。
59.这里,第一设备是指运行测试用例的设备,测试用例用于测试第一源码文件中的源码实现的相关功能。第一设备可以为终端设备或服务器等。第一测试用例泛指用于测试第一源码文件的任意测试用例。第一源码文件可以是待测的业务系统对应的源码文件。第一源码文件采用java编程语言编写。需要说明的是,可以采用一个测试用例来测试第一源码文件中的源码实现的相关功能,也可以采用由多个测试用例构成的测试集,测试第一源码文件中的源码实现的相关功能。
60.第一设备利用java反射机制对第一测试用例中的源码进行扫描,确定出第一测试用例相关的所有mock方法。由于在通过第一测试用例进行测试的过程中,需要调用第一测
试用例相关的mock方法,因此,第一设备在执行第一测试用例之前,激活第一测试用例相关的所有mock方法。处于激活状态的mock方法是已生效的mock方法,允许被调用。实际应用时,可以为每个mock方法添加一个激活标识,激活标识的值为1时表征mock方法生效,激活标识的值为0时表征mock方法失效,将mock方法、激活标识和激活标识的值关联保存在全局缓存中,便于查找与修改mock方法对应的激活标识的值。其中,
61.java反射机制是指在程序处于运行状态的情况下,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
62.mock方法和java方法均类似于函数的概念,是一段用于实现特定功能的源码片段。第一测试用例中相关的mock方法包括mock私有方法和/或mock公共方法。mock私有方法是指私有的mock方法,仅在对应的测试用例中生效,即仅限指定的测试用例调用;mock公共方法是指公共的mock方法,在多个测试用例中生效,即可供任意测试用例复用。mock私有方法的业务逻辑是写入测试用例中的;mock公共方法的业务逻辑未写入测试用例,采用第二注解标识测试用例所引用的至少一个mock公共方法。在对mock公共方法进行分组或分类的情况下,可以为每个分组或分类分配一个id,以第二注解标识测试用例所引用的一组mock公共方法。
63.需要说明的是,由于本技术中的mock方法是按照java方法的语法习惯构造出的,mock方法可以调用java类包括的相关java方法(或称java函数),因此,mock方法中包括的第一声明的格式与第一java方法的第二声明的格式相同。第一java方法是指mock方法所模拟的java方法。
64.在实际应用时,mock方法包括第一注解和第一声明。第一注解用于标识mock方法,供第一设备识别出mock方法;第一声明用于指示mock方法的类型、相关的函数、函数对应的参数以及函数返回值的类型等。mock方法的类型通过访问控制符进行指示,或者由访问控制符和修饰符指示。其中,第一声明至少包括访问控制符、返回值的数据类型、函数名、函数的相关参数和每个参数的数据类型。
65.实际应用时,mock方法的格式可以为:
66.[访问控制符修饰符1修饰符2
…
]函数返回值的类型函数名(函数的相关参数){
[0067]
ꢀꢀꢀꢀ
java语句;
[0068]
}。
[0069]
其中,控制访问符包括public(公共)、private(私有)、protected(受保护的)、默认中的至少之一。修饰符包括表征静态的static或表征不可覆盖重复的final等,当然还可以包括java的其他修饰符。由于mock方法中的第一声明可以包括public或private,还可以包括static或final,因此,本技术中构造出的mock方法支持模拟公共方法、静态方法、私有方法、final不可变方法。
[0070]
示例性地,mock方法可以为:
[0071]
@mockset(target.class)
[0072]
public static int add(int first,int second){
[0073]
ꢀꢀꢀꢀ
//mock测试逻辑
[0074]
}
[0075]
mock方法对应的第一java方法为:
[0076]
public static int add(int first,int second){
[0077]
ꢀꢀꢀꢀ
return first+second;//add方法的业务逻辑
[0078]
}
[0079]
其中,上述mock方法中,@mockset(target.class)为第一注解,target.class为add方法所在的java类;访问控制符为public,修饰符为static,返回值的数据类型为整型(int),java方法名或函数名为add,add方法的参数包括两个整数类型参数first和second。
[0080]
由上述例子可知,构造出的mock方法实际上是用mock测试逻辑替换了对应的第一java方法中add方法的业务逻辑得到。也就是说,开发人员只需要将java方法对应的java类中相关的方法或函数的业务逻辑,替换为,采用java编程语言编写mock测试逻辑,即可得到mock方法。
[0081]
为了提高mock方法的多样性,以更好地满足测试需求,在一些实施例中,所述mock方法包括以下至少之一:
[0082]
公共方法;
[0083]
私有方法;
[0084]
公共静态方法;
[0085]
私有静态方法;
[0086]
包含修饰符final的方法。
[0087]
其中,公共方法中包括控制访问符public;私有方法中包括控制访问符private;公共静态方法中包括控制访问符public和修饰符static;私有静态方法中包括控制访问符private和修饰符static。公共方法和私有方法中均可以包括修饰符final。
[0088]
示例性地,在需要构造一个mock方法来屏蔽java类a的java方法中的query方法的数据库操作的情况下,mock方法可以为:
[0089]
@mockset(a.class)
[0090]
public static int query(string arg){
[0091]
ꢀꢀꢀꢀ
return 100;//屏蔽数据库操作,直接返回测试数据100
[0092]
}。
[0093]
mock方法对应的第一java方法为:
[0094]
public static int query(string arg){
[0095]
ꢀꢀꢀꢀ
查询数据库的源码//查询数据库返回数据逻辑
[0096]
}。
[0097]
在每个mock方法还包括关于mock方法的第一注解的基础上,如图2所示,在一些实施例中,在步骤101之前,所述方法还包括:
[0098]
步骤201:第一设备基于第一测试用例的源码中包括的第一注解,识别出第一测试用例相关的mock方法。
[0099]
这里,第一注解用于标识mock方法,第一注解与mock方法一一对应。第一设备在对第一测试用例进行初始化的过程中,可以通过设定的扫描组件,利用java反射机制对第一测试用例的源码进行扫描,从第一测试用例中识别出第一注解,基于mock方法的第一注解所在的位置,从第一测试用例中确定出mock方法的第一声明;由mock方法的第一声明中包
括控制访问符和修饰符,确定出mock方法的类型,从而得到第一测试用例中第一注解标识的mock方法。其中,设定的扫描组件可以包括reflections扫描工具。同一mock方法对应的第一注解和第一声明位于相邻的两行,且第一注解位于第一声明之前。
[0100]
步骤202:第一设备基于识别出的mock方法的第一注解和第一声明,从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法。
[0101]
这里,第一设备在识别出mock方法的第一注解的情况下,识别出mock方法的第一注解中包括的java类和识别出mock方法的第一声明;利用java反射机制,在第一测试用例对应的第一源码文件中,确定出第二声明与mock方法的第一声明相同的java方法,得到mock方法对应的第一java方法。需要说明的是,未查找到mock方法对应的第一java方法的情况下,输出第一提示信息,第一提示信息用于提示相关人员未查找到mock方法对应的java方法的,例如,未查找到mock方法对应的java方法,请检查mock方法。
[0102]
为了准确地确定出mock方法对应的第一java方法,在一些实施例中,在从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法时,所述方法包括:
[0103]
将第一mock方法的第一注解中的java类、第一mock方法的第一声明包括的第一函数的函数名和第一函数相关的每个参数的数据类型,按照设定方式进行排列,得到第一标识;
[0104]
将java方法的第二声明包括的第二函数的函数名、第二函数的每个参数的数据类型,以及第二函数所属的java类,按照所述设定方式进行排列,得到第二标识;
[0105]
在第一标识和第二标识相同的情况下,将对应的java方法确定为对应的第一mock方法对应的第一java方法。
[0106]
这里,第一mock方法是指第一测试用例中的任一mock方法。第一设备从第一mock方法的第一注解中确定出java类,从第一mock方法的第一声明中确定出第一函数的函数名、第一函数相关的每个参数的数据类型,将确定出的java类、第一函数的函数名以及第一函数相关的每个参数的数据类型,按照设定方式进行排列,得到第一mock方法对应的第一标识。示例性地,在mock方法的第一注解中包含的java类为target,第一声明为public static int add(int first,int second)的情况下,mock方法对应的第一标识为arget@add(int,int)。
[0107]
第一设备从第一源码文件包括的java方法的第二声明中,确定出第二函数的函数名、第二函数相关的每个参数的数据类型,以及确定出第二函数所属的java类,将第二函数所属的java类、第二函数的函数名以及第二函数相关的每个参数的数据类型,按照设定方式进行排列,得到第二标识。
[0108]
将第一mock方法对应的第一标识与确定出的第二标识进行比较,在两者相同的情况下,表征第一mock方法的第一声明与第二标识对应的java方法的第二声明匹配,将第二标识对应的java方法,确定为第一标识对应的第一mock方法对应的第一java方法。在两者不同的情况下,表征第一mock方法的第一声明与java方法的第二声明不匹配。
[0109]
需要说明的是,第一设备可以通过全局缓存组件来缓存第一测试用例相关的mock方法以及mock方法对应的相关信息。其中,mock方法的相关信息包括mock方法的第一注解、激活标识的值以及第一标识。激活标识的值表征mock方法失效或生效。由此,在需要对mock方法进行激活或去激活时,第一设备可以从缓存中直接读取第一测试用例相关的mock方法
的相关信息。
[0110]
考虑到在实际应用时,针对待测试的第一源码文件设置至少一个测试集,每个测试集中包括至少一个测试用例,每个测试用例对应至少一个测试方法,多个测试方法构成一个测试类,每个测试类可以对应至少一个待测试的功能或业务模块。为了避免在每次激活mock方法时均需要解析第一测试用例的源码,第一设备还可以将第一测试用例所属的测试类和第一测试用例中包括的mock私有方法关联存储,由此,第一设备可以基于第一测试用例所属的测试类,从缓存中读取第一测试用例包括的mock私有方法,提高获取第一测试用例相关的mock方法的效率。这里,第一设备可以将第一测试用例所属的测试类和第一测试用例中包括的mock私有方法对应的第一标识关联存储。
[0111]
其中,同一测试集中的不同测试用例可以对应同一个测试类,也可以对应不同的测试类。需要说明的是,由于mock公共方法供多个测试用例复用,为了节省缓存空间,不缓存测试类对应的mock公共方法。
[0112]
步骤203:第一设备基于确定出的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令;其中,所述第一指令用于指示第二设备在第一源码文件中的对应第一java方法中增加第一字节码。
[0113]
这里,第一设备在确定出第一测试用例相关的mock方法对应的第一java方法的情况下,基于确定出的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令。其中,第一指令用于指示第二设备在第一源码文件中的对应第一java方法中增加第一字节码。第一指令可以携带mock方法的第一声明或者第一声明对应的第一标识,以便第二设备在第一源码文件中查找mock方法对应的第一java方法。
[0114]
需要说明的是,第一设备按照步骤201可确定出第一测试用例相关的所有mock方法,针对确定出的每个mock方法,按照步骤202和步骤203进行处理,以便第二设备在第一源码文件中对应的第一java方法中新增对应的第一字节码。
[0115]
步骤204:第二设备基于接收到的第一指令,在第一源码文件中的对应第一java方法中增加第一字节码。
[0116]
这里,第二设备接收到第一设备发送的第一指令的情况下,基于第一指令,在第一源码文件中确定出mock方法对应的第一java方法,并在基于字节码增强技术asm,在确定出的第一java方法中表征业务逻辑的源码之前增加第一字节码。其中,第一字节码用于调用第一java方法对应的mock方法。修改前的java方法和修改后的java方法的示意图如图3所示。
[0117]
在实际应用时,如图3所示,第二设备接收到第一设备发送的第一指令的情况下,基于第一指令,在第一源码文件中确定出对应的第一java方法,并基于字节码增强技术asm,在确定出的第一java方法中表征业务逻辑的源码之前增加第一字节码。
[0118]
在实际应用时,第一字节码表征控制器的实现逻辑。控制器用于判断第一java方法对应的mock方法是否被激活,并在对应的mock方法未被激活时指示第二设备调用第一java方法进行测试,以及在对应的mock方法被激活时指示第二设备调用对应的mock方法进行测试,并在调用对应的mock方法测试完成时指示第二设备判断是否调用第一java方法。也就是说,控制器用于实现图4对应的处理逻辑。
[0119]
本实施例中,在执行第一测试用例之前,基于第一测试用例相关的每个mock方法
对应的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令,以便接收到第一指令的第二设备基于第一指令,在对应的第一java方法中表征业务逻辑的源码之前增加第一字节码。由此,第二设备在调用对应的第一java方法,且执行第一java方法中的业务逻辑的相关指令之前,执行第一字节码,以通过执行第一字节码来调用对应的mock方法进行测试。
[0120]
考虑到在实际应用中可能需要采用至少一个测试集对第一源码文件进行测试,而一个测试集中包括多个测试用例,在一些实施例中,所述激活所述第一测试用例相关的所有mock方法,包括以下至少之一:
[0121]
解析出第一测试用例所属的测试类,以及基于预先缓存的测试类和mock方法之间的对应关系,确定出第一测试用例相关的第一类mock方法;第一类mock方法的访问控制符为private;
[0122]
基于第一测试用例的源码中包括的第二注解,确定出第一测试用例相关的第二类mock方法;其中,第二注解表征第一测试用例引用的一组公共的mock方法;第二类mock方法的访问控制符为public。
[0123]
这里,第一设备在对第一测试集完成初始化之后,且在执行第一测试用例之前,需要激活第一测试用例相关的所有mock方法,此时,第一设备解析第一测试用例的源码,从第一测试用例中解析出第一测试用例所属的测试类,基于预先缓存的测试类和mock方法之间的对应关系,确定出解析出的测试类对应的mock方法,得到第一测试用例相关的第一类mock方法;或者,第一设备从第一测试用例中识别出第二注解,根据确定出的第二注解包括的第三标识,确定出第一测试用例相关的第二类mock方法。第三标识为一组公共的mock方法对应的分组标识。
[0124]
在实际应用时,第一设备对第一测试用例完成初始化后,通过拦截器拦截运行的第一测试用例,在拦截器中解析出第一测试用例所属的测试类以及解析出第一测试用例中包含的第二注解,基于预先缓存的测试类和mock方法之间的对应关系,确定出解析出的测试类对应的第一类mock方法,以及从第二注解中包括的第三标识,确定出第一测试用例相关的第二类mock方法。
[0125]
在实际应用中,第一设备在全局缓存组件中已关联存储第一测试用例所属的测试类和第一测试用例中包括的mock私有方法的情况下,第一设备在识别出第一类mock方法的情况下,在全局缓存组件中查找与识别出的第一类mock方法相同的mock私有方法,在查找到与识别出的第一类mock方法相同的mock私有方法的情况下,激活识别出的第一类mock方法。由此,可以防止因测试用例中的mock方法被恶意篡改,而执行错误的mock方法的情况发生。
[0126]
需要说明的是,第一设备可以每确定出一个mock方法,就激活一个mock方法,并修改全局缓存组件中对应的mock方法的激活标识的值;也可以在识别出第一测试用例相关的所有mock方法的情况下,激活识别出的所有mock方法。
[0127]
在实际应用中,可以通过mock方法管理器来统一管理mock方法的生命周期,在拦截器中调用mock方法管理器对第一测试用例相关的mock方法进行激活或去激活。
[0128]
步骤102:第一设备在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;其中,第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一
java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
[0129]
这里,考虑到本技术主要对利用mock技术进行软件测试的方法进行了改进,因此,本技术中重点介绍调用mock方法进行测试的实现过程。
[0130]
第一设备在激活第一测试用例相关的所有mock方法之后,执行第一测试用例,以通过第一测试用例对第一源码文件对应实现的功能进行测试。在执行第一测试用例的过程中,向运行第一源码文件中的源码的第二设备发送第一测试指令,第一测试指令用于指示第二设备调用被测试的第一源码文件中的第一java方法进行测试,以便第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法在第一测试用例中对应的mock方法进行测试。
[0131]
需要说明的是,第二设备可以为终端设备或服务器等。第一java方法中的第一字节码是在步骤102之前,根据第一测试用例中相关的mock方法写入。
[0132]
步骤103:第二设备接收第一设备在执行第一测试用例的过程中发送的第一测试指令。
[0133]
这里,第二电子设备在对第一源码文件完成初始化的情况下,接收第一设备发送的第一测试指令。
[0134]
步骤104:第二设备在调用第一java方法进行测试之前,执行对应的第一字节码,以反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
[0135]
这里,第二设备在接收到第一测试指令的情况下,基于第一测试指令调用第一java方法,并在第一源码文件中识别出第一java方法时,先执行对应的第一字节码;通过执行对应的第一字节码,反射调用第一java方法在第一测试用例中对应的mock方法,并将第一java方法中的入参数据传入对应的mock方法进行测试。其中,第一字节码位于第一java方法中表征业务逻辑的所有源码之前,例如步骤101中示出的第一java方法,对应的第一字节码位于表征add方法的业务逻辑的源码之前。反射调用是指利用java反射机制进行调用。
[0136]
需要说明的是,在执行完对应的mock方法之后,可以执行第一java方法中用于实现相关业务逻辑的指令,从而按照第一java方法对应的业务逻辑进行测试,也可以不执行第一java方法中用于实现相关业务逻辑的指令,结束调用第一java方法。其中,在执行完对应的mock方法之后,是否执行第一java方法中用于实现相关业务逻辑的指令进行测试,由对应的mock方法中的测试逻辑决定。也就是说,在执行对应的mock方法的过程中,支持调用第一java方法,以执行第一java方法中用于实现相关业务逻辑的指令。
[0137]
在实际应用中,在构造mock方法时,可保持原java方法的声明的格式不变,在方法参数中引入java方法的对象引用,通过该对象引用即可调用java方法。需要说明的是,mock方法调用的java方法,可以是增加第一字节码之前的第一java方法;也可以是除第一java方法之外的其他的java方法,例如在第一java方法c中增加了第一字节码,第一字节码用于反射调用mock方法b,mock方法b中引入了对象b,对象b中包括java方法a,此时,可以在mock方法b中调用java方法a。示例性地,在通过对象引用来调用原java方法,且原java方法为add方法的情况下,构造出的mock方法如下:
[0138]
@mockset(target.class)
[0139]
public static int add(target self,int first,int second){
[0140]
ꢀꢀꢀꢀ
//mock测试逻辑
[0141]
ꢀꢀꢀꢀ
//self调用原java方法(add方法)
[0142]
}。
[0143]
其中,target self表征对象引用。
[0144]
在一些实施例中,所述执行所述第一字节码,包括:
[0145]
在所述第一java方法对应的mock方法处于激活状态的情况下,通过反射调用所述第一java方法对应的mock方法,执行所述第一java方法对应的mock方法相关的指令;或者
[0146]
在所述第一java方法对应的mock方法处于未激活状态的情况下,调用所述第一java方法进行测试。
[0147]
这里,如图4所示,第一字节码用于指示第二设备判断第一java方法对应的mock方法是否处于激活状态,以及在对应的mock方法处于激活状态的情况下,指示第二设备执行第一java方法对应的mock方法相关的指令进行测试;在对应的mock方法处于未激活状态的情况下,指示第二设备调用第一java方法进行测试。
[0148]
第二设备在执行第一字节码的过程中,判断第一java方法对应的mock方法是否处于激活状态,得到判断结果。
[0149]
在该判断结果指示第一java方法对应的mock方法处于未激活状态的情况下,表征不需要调用对应的mock方法,此时,调用第一java方法进行测试。
[0150]
在该判断结果指示第一java方法对应的mock方法处于激活状态的情况下,表征需要调用对应的mock方法进行测试,此时,通过反射调用所述第一java方法对应的mock方法,执行第一java方法对应的mock方法相关的指令;在对应的mock方法相关的指令指示执行对应的第一java方法的情况下,在执行完mock方法之后,执行对应的第一java方法中用于实现相关业务逻辑的指令进行测试,在对应的mock方法相关的指令指示不执行对应的第一java方法的情况下,在执行完mock方法之后,不执行第一java方法中用于实现相关业务逻辑的指令。
[0151]
在实际应用时,在步骤104之前,通过全局缓存组件关联缓存了第一测试用例相关的mock方法、对应的激活标识的值和第一标识的情况下,第二设备可以基于第一java方法的第二声明,确定出第一java方法对应的第二标识,从全局缓存组件中查找与确定出的第二标识相同的第一标识,并确定出查找到的第一标识对应的激活标识的值,通过该激活标识的值,来确定第一java方法对应的mock方法是否处于激活状态。其中,确定第二标识的方法请参照步骤202中的相关描述,此处不赘述。
[0152]
步骤105:第一设备在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活。
[0153]
这里,第一设备在执行完第一测试用例的情况下,对已激活的所有mock方法进行去激活,从而使得第一测试用例相关的所有mock方法失效,此时,mock方法的状态从已激活状态切换为未激活状态。
[0154]
需要说明的是,本实施例中通过对mock方法进行激活或去激活,来指示第二设备是否调用mock方法进行测试,可以减少对测试用例的源码的修改操作。
[0155]
在本技术实施例中,在利用mock技术进行软件测试时,第一设备在执行第一测试
用例之前,激活所述第一测试用例相关的所有mock方法,并在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;接收到第一测试指令的第二设备在调用第一java方法进行测试之前,执行第一java方法中的第一字节码,以反射调用第一java方法在第一测试用例中对应的mock方法进行测试;第一设备在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活。其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同。本方案中,测试用例中的mock方法是按照java的语法习惯构造出的,测试用例中的mock方法包括的声明与java方法的声明相同,在构造mock方法时,将原java方法的业务逻辑替换为mock方法的测试逻辑即可,由此,可以简化构造mock方法的语法,提高构造mock方法的效率较和降低构造出的mock方法存在语法错误的概率,进而提高测试效率。
[0156]
图5为本技术应用实施例提供的一种软件测试方法的交互图。
[0157]
步骤501:第一设备基于第一测试用例的源码中包括的第一注解,识别出第一测试用例相关的mock方法;其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同。
[0158]
这里,在第一设备对第一测试用例进行初始化以及第二设备对第一源码文件进行初始化的过程中,第一设备执行步骤501,将识别出的mock方法的相关信息,与第一测试用例的用例标识关联存储至全局缓存组件中。其中,mock方法的相关信息包括mock方法的第一注解、激活标识的值以及第一标识。步骤501的实现过程请参照步骤201的相关描述,此处不赘述。
[0159]
实际应用时,第一设备对第一测试用例进行初始化以及第二设备对第一源码文件进行初始化的过程,如图6所示。
[0160]
步骤502:第一设备基于识别出的mock方法的第一注解和第一声明,从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法。
[0161]
这里,第一设备可以遍历全局缓存组件中缓存的mock方法,针对每个mock方法,执行步骤502。步骤502的实现过程请参照步骤202的相关描述,此处不赘述。
[0162]
第一设备在确定出第一测试用例相关的每个mock方法对应的第一java方法的情况下,初始化拦截器,拦截器用于在拦截启动的测试用例。
[0163]
步骤503:第一设备基于确定出的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令;其中,所述第一指令用于指示第二设备在第一源码文件中的对应第一java方法中增加第一字节码。
[0164]
其中,步骤503的实现过程请参照步骤203的相关描述,此处不赘述。
[0165]
步骤504:第二设备基于接收到的第一指令,在第一源码文件中的对应第一java方法中增加第一字节码。
[0166]
其中,步骤504的实现过程请参照步骤204的相关描述,此处不赘述。
[0167]
在实际应用时,第一字节码表征控制器的实现逻辑。控制器用于实现图4对应的处理逻辑。
[0168]
步骤505:第一设备在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法。
[0169]
这里,第一设备通过拦截器拦截启动的第一测试用例,通过以下至少之一识别出
待激活的mock方法:
[0170]
解析出第一测试用例所属的测试类,以及基于预先缓存的测试类和mock方法之间的对应关系,确定出第一测试用例相关的第一类mock方法;第一类mock方法的访问控制符为private;
[0171]
基于第一测试用例的源码中包括的第二注解,确定出第一测试用例相关的第二类mock方法;其中,第二注解表征第一测试用例引用的一组公共的mock方法;第二类mock方法的访问控制符为public。
[0172]
第一设备在执行第一测试用例之前,激活第一测试用例相关的所有mock方法。在激活mock方法之后,可以在全局缓存组件中,修改对应的mock方法对应的激活标识的值。
[0173]
在实际应用中,在通过mock方法管理器来统一管理mock方法的生命周期的情况下,在拦截器中调用mock方法管理器对第一测试用例相关的mock方法进行激活或去激活。
[0174]
为了防止因测试用例中的mock方法被恶意篡改,而执行错误的mock方法的情况发生,第一设备在确定出第一类mock方法的情况下,在全局缓存组件中查找与识别出的第一类mock方法相同的mock私有方法,在查找到与识别出的第一类mock方法相同的mock私有方法的情况下,激活识别出的第一类mock方法。这里,第一设备可以基于第一类mock方法的第一声明对应的第一标识,在全局缓存组件中查找与该第一标识相同的第一标识。
[0175]
步骤506:第一设备在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;其中,第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
[0176]
其中,步骤506的实现过程请参照步骤102的相关描述,此处不赘述。
[0177]
步骤507:第二设备接收第一设备在执行第一测试用例的过程中发送的第一测试指令。
[0178]
步骤508:第二设备在调用第一java方法进行测试之前,执行对应的第一字节码,以反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
[0179]
步骤509:第一设备在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活。
[0180]
为实现本技术实施例的应用于第一设备的软件测试方法,本技术实施例还提供了一种电子设备,如图7所示,该电子设备包括:
[0181]
激活单元71,用于在执行第一测试用例之前,激活所述第一测试用例相关的所有mock方法;其中,每个mock方法中包括第一声明,且第一声明的格式与mock方法对应的第一java方法的第二声明的格式相同;
[0182]
测试单元72,用于在执行所述第一测试用例的过程中,向第二设备发送第一测试指令;
[0183]
去激活单元73,用于在执行完所述第一测试用例的情况下,对已激活的所有mock方法进行去激活;其中,
[0184]
第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调
用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试。
[0185]
在一些实施例中,每个mock方法还包括关于mock方法的第一注解;该电子设备还包括:
[0186]
识别单元,用于基于第一测试用例的源码中包括的第一注解,识别出第一测试用例相关的mock方法;
[0187]
确定单元,用于基于识别出的mock方法的第一注解和第一声明,从第一测试用例对应的第一源码文件中确定出mock方法对应的第一java方法;发送单元,用于基于确定出的第一java方法,向运行对应的第一源码文件中的源码的第二设备发送第一指令;其中,所述第一指令用于指示第二设备在第一源码文件中的对应第一java方法中增加第一字节码。
[0188]
在一些实施例中,识别单元用于执行以下至少之一:
[0189]
解析出第一测试用例所属的测试类,以及基于预先缓存的测试类和mock方法之间的对应关系,确定出第一测试用例相关的第一类mock方法;第一类mock方法的访问控制符为private;
[0190]
基于第一测试用例的源码中包括的第二注解,确定出第一测试用例相关的第二类mock方法;其中,第二注解表征第一测试用例引用的一组公共的mock方法;第二类mock方法的访问控制符为public。
[0191]
在一些实施例中,确定单元具体用于:
[0192]
将第一mock方法的第一注解中的java类、第一mock方法的第一声明包括的第一函数的函数名和第一函数相关的每个参数的数据类型,按照设定方式进行排列,得到第一标识;
[0193]
将java方法的第二声明包括的第二函数的函数名、第二函数的每个参数的数据类型,以及第二函数所属的java类,按照所述设定方式进行排列,得到第二标识;
[0194]
在第一标识和第二标识相同的情况下,将对应的java方法确定为对应的第一mock方法对应的第一java方法。
[0195]
在一些实施例中,所述mock方法包括以下至少之一:
[0196]
公共方法;
[0197]
私有方法;
[0198]
公共静态方法;
[0199]
私有静态方法;
[0200]
包含修饰符final的方法。
[0201]
实际应用时,上述各单元可由电子设备中的处理器,比如中央处理器(cpu,central processing unit)、数字信号处理器(dsp,digital signal processor)、微控制单元(mcu,microcontroller unit)或可编程门阵列(fpga,field-programmable gate array)等实现,或者由电子设备中的处理器和通信接口共同实现。当然,处理器需要运行存储器中存储的程序来实现上述各程序模块的功能。
[0202]
需要说明的是:上述实施例提供的电子设备在进行软件测试时,仅以上述各程序模块的划分进行举例说明,实际应用中,可以根据需要而将上述处理分配由不同的程序模块完成,即将装置的内部结构划分成不同的程序模块,以完成以上描述的全部或者部分处理。另外,上述实施例提供的电子设备与应用于第一设备的软件测试方法实施例属于同一
构思,其具体实现过程详见方法实施例,这里不再赘述。
[0203]
为实现本技术实施例的应用于第二设备的软件测试方法,本技术实施例还提供了一种电子设备,如图8所示,该电子设备包括:
[0204]
接收单元81,用于接收第一设备在执行第一测试用例的过程中发送的第一测试指令;其中,所述第一测试指令用于指示所述第二设备调用被测试的第一源码文件中的第一java方法进行测试;第一java方法中设有第一字节码;第一字节码用于指示所述第二设备在调用对应的第一java方法进行测试之前,反射调用第一java方法对应的mock方法进行测试;
[0205]
测试单元82,用于在调用所述第一java方法进行测试之前,执行所述第一字节码,以反射调用第一java方法在所述第一测试用例中对应的mock方法进行测试。
[0206]
在一些实施例中,测试单元82具体用于:
[0207]
在所述第一java方法对应的mock方法处于激活状态的情况下,通过反射调用所述第一java方法对应的mock方法,执行所述第一java方法对应的mock方法相关的指令;或者
[0208]
在所述第一java方法对应的mock方法处于未激活状态的情况下,调用所述第一java方法进行测试。
[0209]
实际应用时,测试单元82可由电子设备中的处理器,比如中央处理器(cpu,central processing unit)、数字信号处理器(dsp,digital signal processor)、微控制单元(mcu,microcontroller unit)或可编程门阵列(fpga,field-programmable gate array)等实现,接收单元81可由电子设备中的处理器和通信接口共同实现。当然,处理器需要运行存储器中存储的程序来实现上述各程序模块的功能。
[0210]
需要说明的是:上述实施例提供的电子设备在进行软件测试时,仅以上述各程序模块的划分进行举例说明,实际应用中,可以根据需要而将上述处理分配由不同的程序模块完成,即将装置的内部结构划分成不同的程序模块,以完成以上描述的全部或者部分处理。另外,上述实施例提供的电子设备与应用于第一设备的软件测试方法实施例属于同一构思,其具体实现过程详见方法实施例,这里不再赘述。
[0211]
基于上述程序模块的硬件实现,且为了实现本技术实施例的方法,本技术实施例还提供了一种电子设备。图9为本技术实施例提供的电子设备的硬件组成结构示意图,如图9所示,电子设备9包括:
[0212]
通信接口91,能够与其它设备比如网络设备等进行信息交互;
[0213]
处理器92,与所述通信接口91连接,以实现与其它设备进行信息交互,用于运行计算机程序时,执行上述应用于第一设备的一个或多个技术方案提供的软件测试方法,或者执行上述应用于第二设备的一个或多个技术方案提供的软件测试方法。而所述计算机程序存储在存储器93上。
[0214]
当然,实际应用时,电子设备9中的各个组件通过总线系统94耦合在一起。可理解,总线系统94用于实现这些组件之间的连接通信。总线系统94除包括数据总线之外,还包括电源总线、控制总线和状态信号总线。但是为了清楚说明起见,在图9中将各种总线都标为总线系统94。
[0215]
本技术实施例中的存储器93用于存储各种类型的数据以支持电子设备9的操作。这些数据的示例包括:用于在电子设备9上操作的任何计算机程序。
[0216]
可以理解,存储器93可以是易失性存储器或非易失性存储器,也可包括易失性和非易失性存储器两者。其中,非易失性存储器可以是只读存储器(rom,read only memory)、可编程只读存储器(prom,programmable read-only memory)、可擦除可编程只读存储器(eprom,erasable programmable read-only memory)、电可擦除可编程只读存储器(eeprom,electrically erasable programmable read-only memory)、磁性随机存取存储器(fram,ferromagnetic random access memory)、快闪存储器(flash memory)、磁表面存储器、光盘、或只读光盘(cd-rom,compact disc read-only memory);磁表面存储器可以是磁盘存储器或磁带存储器。易失性存储器可以是随机存取存储器(ram,random access memory),其用作外部高速缓存。通过示例性但不是限制性说明,许多形式的ram可用,例如静态随机存取存储器(sram,static random access memory)、同步静态随机存取存储器(ssram,synchronous static random access memory)、动态随机存取存储器(dram,dynamic random access memory)、同步动态随机存取存储器(sdram,synchronous dynamic random access memory)、双倍数据速率同步动态随机存取存储器(ddrsdram,double data rate synchronous dynamic random access memory)、增强型同步动态随机存取存储器(esdram,enhanced synchronous dynamic random access memory)、同步连接动态随机存取存储器(sldram,synclink dynamic random access memory)、直接内存总线随机存取存储器(drram,direct rambus random access memory)。本技术实施例描述的存储器93旨在包括但不限于这些和任意其它适合类型的存储器。
[0217]
上述本技术实施例揭示的方法可以应用于处理器92中,或者由处理器92实现。处理器92可能是一种集成电路芯片,具有信号的处理能力。在实现过程中,上述方法的各步骤可以通过处理器92中的硬件的集成逻辑电路或者软件形式的指令完成。上述的处理器92可以是通用处理器、dsp,或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。处理器92可以实现或者执行本技术实施例中的公开的各方法、步骤及逻辑框图。通用处理器可以是微处理器或者任何常规的处理器等。结合本技术实施例所公开的方法的步骤,可以直接体现为硬件译码处理器执行完成,或者用译码处理器中的硬件及软件模块组合执行完成。软件模块可以位于存储介质中,该存储介质位于存储器93,处理器92读取存储器93中的程序,结合其硬件完成前述方法的步骤。
[0218]
可选地,所述处理器92执行所述程序时实现本技术实施例的各个方法中由终端实现的相应流程,为了简洁,在此不再赘述。
[0219]
在示例性实施例中,本技术实施例还提供了一种存储介质,即计算机存储介质,具体为计算机可读存储介质,例如包括存储计算机程序的第一存储器93,上述计算机程序可由终端的处理器92执行,以完成前述方法所述步骤。计算机可读存储介质可以是fram、rom、prom、eprom、eeprom、flash memory、磁表面存储器、光盘、或cd-rom等存储器。
[0220]
在本技术所提供的几个实施例中,应该理解到,所揭露的设备和方法,可以通过其它的方式实现。以上所描述的设备实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,如:多个单元或组件可以结合,或可以集成到另一个系统,或一些特征可以忽略,或不执行。另外,所显示或讨论的各组成部分相互之间的耦合、或直接耦合、或通信连接可以是通过一些接口,设备或单元的间接耦合或通信连接,可以是电性的、机械的或其它形式的。
[0221]
上述作为分离部件说明的单元可以是、或也可以不是物理上分开的,作为单元显示的部件可以是、或也可以不是物理单元,即可以位于一个地方,也可以分布到多个网络单元上;可以根据实际的需要选择其中的部分或全部单元来实现本实施例方案的目的。
[0222]
另外,在本发明各实施例中的各功能单元可以全部集成在一个处理模块中,也可以是各单元分别单独作为一个单元,也可以两个或两个以上单元集成在一个单元中;上述集成的单元既可以采用硬件的形式实现,也可以采用硬件加软件功能单元的形式实现。
[0223]
本领域普通技术人员可以理解:实现上述方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成,前述的程序可以存储于一计算机可读取存储介质中,该程序在执行时,执行包括上述方法实施例的步骤;而前述的存储介质包括:移动存储设备、只读存储器(rom,read-only memory)、随机存取存储器(ram,random access memory)、磁碟或者光盘等各种可以存储程序代码的介质。
[0224]
需要说明的是,本发明实施例所记载的技术方案之间,在不冲突的情况下,可以任意组合。
[0225]
需要说明的是,本发明实施例中的术语“和/或”,仅仅是一种描述关联对象的关联关系,表示可以存在三种关系,例如,a和/或b,可以表示:单独存在a,同时存在a和b,单独存在b这三种情况。另外,本文中术语“至少一种”表示多个中的任意一种或多种中的至少两种的任意组合,例如,包括a、b、c中的至少一种,可以表示包括从a、b和c构成的集合中选择的任意一个或多个元素。
[0226]
以上所述,仅为本发明的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本发明揭露的技术范围内,可轻易想到变化或替换,都应涵盖在本发明的保护范围之内。因此,本发明的保护范围应以所述权利要求的保护范围为准。