异步接口的测试方法、介质、装置和计算设备与流程

文档序号:15557714发布日期:2018-09-29 01:31阅读:248来源:国知局
本发明的实施方式涉及通信及计算机
技术领域
:,更具体地,本发明的实施方式涉及异步接口的测试方法、介质、装置和计算设备。
背景技术
::本部分旨在为权利要求书中陈述的本发明的实施方式提供背景或上下文。此处的描述不因为包括在本部分中就承认是现有技术。在移动应用开发过程中,通常需要对软件进行功能模块的划分,并将每个独立的功能模块以软件库的形式进行开发,通常称为sdk(softwaredevelopmentkit,软件开发工具包)。比如对于网易云信这款即时通讯sdk,它以接口形式对外提供各种功能,例如发送消息接口、创建群组接口、添加好友接口等等,软件开发者通过调用它提供的api(applicationprogramminginterface,应用程序编程接口)能快速在自身应用中集成即时通讯功能。技术实现要素:但是,目前在对上述sdk的接口进行测试时,一种方式是采用传统的手工测试方案,这种测试方案虽然门槛低,起步比较容易,但是随着接口数量的增加,测试工作量会成倍增长,进而会导致测试效率低、准确性低。同时,目前采用的自动化测试方案不便于对异步接口进行测试,这是由于测试用例在单独线程执行,而对异步接口的测试断言却在异步回调线程中进行,这样会造成测试用例没有断言便已经执行结束的问题,导致无法达到测试异步接口的目的。为此,非常需要一种改进的异步接口的测试方案,以避免现有的自动化测试方案在测试用例还未断言就已经执行结束的问题,同时能够简化对异步接口测试用例的复杂度,提高测试开发效率。在本上下文中,本发明的实施方式期望提供一种异步接口的测试方法、介质、装置和计算设备。在本发明实施方式的第一方面中,提供了一种异步接口的测试方法,包括:通过测试线程调用待测试的异步接口;在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程;在阻塞所述测试线程的期间内,对所述异步接口进行测试断言;在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,在通过测试线程调用待测试的异步接口之前,还包括:生成一测试结果类和线程阻塞类,将所述线程阻塞类作为所述测试结果类的成员变量;实例化所述测试结果类,以得到测试结果对象和所述线程阻塞对象;将所述测试结果对象设置为所述异步接口的回调对象。在本发明的一些实施例中,基于前述方案,对所述异步接口进行测试断言,包括:根据所述异步接口的回调结果,确定所述异步接口的实际返回码,或确定所述异步接口的实际返回码和返回数据;根据所述实际返回码和预期返回码,或根据所述实际返回码、所述返回数据和预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,在通过测试线程调用待测试的异步接口之前,还包括:创建一调用结果对象,将所述调用结果对象作为所述异步接口的直接返回类型;以所述调用结果对象和预期返回码作为输入参数,构建异步接口验证方法,并在所述异步接口验证方法中封装所述线程阻塞对象;执行所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,对所述异步接口进行测试断言,包括:将所述调用结果对象的值作为所述异步接口的实际返回码,根据所述实际返回码和所述预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述调用结果对象的成员变量包含一回调对象,所述异步接口回调时调用所述回调对象;所述方法还包括:在构建所述异步接口验证方法时,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,对所述异步接口进行测试断言,包括:将所述调用结果对象的值作为所述异步接口的实际返回码,将所述回调对象的值作为所述异步接口的返回数据,根据所述实际返回码、所述预期返回码和所述返回数据,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法,包括:生成回调对象数组和调用结果对象数组,所述回调对象数组中的回调对象与所述调用结果对象数组中的调用结果对象一一对应;将所述回调对象数组、所述调用结果对象数组和所述预期返回码作为输入参数,构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行,包括:在根据每一对所述回调对象和所述调用结果对象进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述异步接口验证方法所归属的类为基类的派生类。在本发明的一些实施例中,基于前述方案,所述的方法还包括:获取包含有所述预期返回码的自定义注解;解析所述自定义注解,以获取所述预期返回码。在本发明的一些实施例中,基于前述方案,获取包含有所述预期返回码的自定义注解,包括:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的所述自定义注解。在本发明的一些实施例中,基于前述方案,所述的方法还包括:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的自定义注解,所述自定义注解中包含有用于生成测试报告的信息;解析所述自定义注解,以得到所述用于生成测试报告的信息;根据所述用于生成测试报告的信息和对所述异步接口进行测试断言的结果,生成测试报告。在本发明的一些实施例中,基于前述方案,所述用于生成测试报告的信息包括:待测试的异步端口、测试步骤、预期返回码。在本发明的一些实施例中,基于前述方案,基于所述线程阻塞对象阻塞所述测试线程,包括:调用所述线程阻塞对象中的wait方法,以使所述测试线程进入阻塞状态。在本发明的一些实施例中,基于前述方案,基于所述线程阻塞对象使所述测试线程继续执行,包括:调用所述线程阻塞对象中的notify方法,以使所述测试线程重新进入执行状态。在本发明实施方式的第二方面中,提供了一种介质,其上存储有程序,该程序被处理器执行时实现如上述实施例中第一方面所述的方法。在本发明实施方式的第三方面中,提供了一种异步接口的测试装置,包括:调用单元,用于通过测试线程调用待测试的异步接口;阻塞单元,用于在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程;处理单元,用于在阻塞所述测试线程的期间内,对所述异步接口进行测试断言;恢复单元,用于在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述的装置还包括:第一生成单元,用于在通过测试线程调用待测试的异步接口之前,生成一测试结果类和线程阻塞类,将所述线程阻塞类作为所述测试结果类的成员变量;实例化单元,用于实例化所述测试结果类,以得到测试结果对象和所述线程阻塞对象,并将所述测试结果对象设置为所述异步接口的回调对象。在本发明的一些实施例中,基于前述方案,所述处理单元配置为:根据所述异步接口的回调结果,确定所述异步接口的实际返回码,或确定所述异步接口的实际返回码和返回数据;根据所述实际返回码和预期返回码,或根据所述实际返回码、所述返回数据和预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述的装置还包括:创建单元,用于在通过测试线程调用待测试的异步接口之前,创建一调用结果对象,将所述调用结果对象作为所述异步接口的直接返回类型;构建单元,用于以所述调用结果对象和预期返回码作为输入参数,构建异步接口验证方法,并在所述异步接口验证方法中封装所述线程阻塞对象;执行单元,用于执行所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述处理单元配置为:将所述调用结果对象的值作为所述异步接口的实际返回码,根据所述实际返回码和所述预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述调用结果对象的成员变量包含一回调对象,所述异步接口回调时调用所述回调对象;所述构建单元用于:在构建所述异步接口验证方法时,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述处理单元配置为:将所述调用结果对象的值作为所述异步接口的实际返回码,将所述回调对象的值作为所述异步接口的返回数据,根据所述实际返回码、所述预期返回码和所述返回数据,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述构建单元配置为:生成回调对象数组和调用结果对象数组,所述回调对象数组中的回调对象与所述调用结果对象数组中的调用结果对象一一对应;将所述回调对象数组、所述调用结果对象数组和所述预期返回码作为输入参数,构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述恢复单元配置为:在根据每一对所述回调对象和所述调用结果对象进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述异步接口验证方法所归属的类为基类的派生类。在本发明的一些实施例中,基于前述方案,所述的装置还包括:第一获取单元,用于获取包含有所述预期返回码的自定义注解;第一解析单元,用于解析所述自定义注解,以获取所述预期返回码。在本发明的一些实施例中,基于前述方案,所述第一获取单元配置为:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的所述自定义注解。在本发明的一些实施例中,基于前述方案,所述的装置还包括:第二获取单元,用于在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的自定义注解,所述自定义注解中包含有用于生成测试报告的信息;第二解析单元,用于解析所述自定义注解,以得到所述用于生成测试报告的信息;第二生成单元,用于根据所述用于生成测试报告的信息和对所述异步接口进行测试断言的结果,生成测试报告。在本发明的一些实施例中,基于前述方案,所述用于生成测试报告的信息包括:待测试的异步端口、测试步骤、预期返回码。在本发明的一些实施例中,基于前述方案,所述阻塞单元配置为:调用所述线程阻塞对象中的wait方法,以使所述测试线程进入阻塞状态。在本发明的一些实施例中,基于前述方案,所述恢复单元配置为:调用所述线程阻塞对象中的notify方法,以使所述测试线程重新进入执行状态。在本发明实施方式的第四方面中,提供了一种计算设备,包括:处理器和存储器,所述存储器存储有可执行指令,所述处理器用于调用所述存储器存储的可执行指令执行如上述实施例中第一方面所述的方法。根据本发明实施方式的异步接口的测试方法、介质、装置和计算设备,通过在调用异步接口之后,基于线程阻塞对象阻塞测试线程,在阻塞测试线程的期间内,对异步接口进行测试断言,并在对异步接口进行测试断言之后,基于线程阻塞对象使测试线程继续执行,使得在对异步接口进行测试时,能够通过线程阻塞对象阻塞测试线程,以等待对异步接口的测试及断言,避免了现有的自动化测试方案在测试用例还未断言就已经执行结束的问题,同时也解决了异步接口测试困难的问题,实现了对异步接口的便捷测试,简化了对异步接口测试用例的复杂度,提高了测试开发效率。附图说明通过参考附图阅读下文的详细描述,本发明示例性实施方式的上述以及其他目的、特征和优点将变得易于理解。在附图中,以示例性而非限制性的方式示出了本发明的若干实施方式,其中:图1示意性示出了根据本发明的一个实施例的异步接口的测试方法的流程图;图2示意性示出了根据本发明的另一个实施例的异步接口的测试方法的流程图;图3示意性示出了根据本发明的又一个实施例的异步接口的测试方法的流程图;图4示意性示出了根据本发明的一个实施例的生成测试报告的流程图;图5示出了根据本发明的实施例的waitable的执行过程示意图;图6示出了根据本发明的实施例的checkreponse方法的执行过程示意图;图7示出了根据本发明的一个实施例的测试用例的执行过程示意图;图8示出了根据本发明的另一个实施例的测试用例的执行过程示意图;图9示出了根据本发明的一个实施例的测试报告的示意图;图10示出了根据本发明的另一个实施例的测试报告的示意图;图11示意性示出了根据本发明的实施例的异步接口的测试装置的框图。在附图中,相同或对应的标号表示相同或对应的部分。具体实施方式下面将参考若干示例性实施方式来描述本发明的原理和精神。应当理解,给出这些实施方式仅仅是为了使本领域技术人员能够更好地理解进而实现本发明,而并非以任何方式限制本发明的范围。相反,提供这些实施方式是为了使本发明更加透彻和完整,并且能够将本发明的范围完整地传达给本领域的技术人员。本领域技术人员知道,本发明的实施方式可以实现为一种系统、装置、设备、方法或计算机程序产品。因此,本发明可以具体实现为以下形式,即:完全的硬件、完全的软件(包括固件、驻留软件、微代码等),或者硬件和软件结合的形式。根据本发明的实施方式,提出了一种异步接口的测试方法、介质、装置和计算设备。在本文中,需要理解的是,所涉及的术语“sdk”通常是指软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立的应用软件开发工具的集合。术语“api”通常是指一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。术语“成员变量”是指在类体的变量部分中定义的变量,也称为字段。术语“注解”即为annotation,也叫元数据,是一种代码级别的说明。java注解是jdk1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次,它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明和注释。术语“回调”即callback,是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。术语“异步接口”是与“同步接口”相对应的,异步接口实现的是异步交互,比如发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。同步接口实现的是同步交互,比如发送一个请求之后,需要等待返回,然后才能够发送下一个请求,有个等待过程。此外,附图中的任何元素数量均用于示例而非限制,以及任何命名都仅用于区分,而不具有任何限制含义。下面参考本发明的若干代表性实施方式,详细阐释本发明的原理和精神。发明概述本发明人发现,目前在对上述sdk的接口进行测试时,一种方式是采用传统的手工测试方案,这种测试方案虽然门槛低,起步比较容易,但是随着接口数量的增加,测试工作量会成倍增长,进而会导致测试效率低、准确性低。同时,目前采用的自动化测试方案不便于对异步接口进行测试,这是由于测试用例在单独线程执行,而对异步接口的测试断言却在异步回调线程中进行,这样会造成测试用例没有断言便已经执行结束的问题,导致无法达到测试异步接口的目的。因此,本发明的实施例提供了一种异步接口的测试方法、介质、装置和计算设备,可以避免现有的自动化测试方案在测试用例还未断言就已经执行结束的问题,同时能够简化对异步接口测试用例的复杂度,提高了测试开发效率。在介绍了本发明的基本原理之后,下面具体介绍本发明的各种非限制性实施方式。应用场景总览需要注意的是,下述应用场景仅是为了便于理解本发明的精神和原理而示出,本发明的实施方式在此方面不受任何限制。相反,本发明的实施方式可以应用于适用的任何场景。应用场景一:在对异步接口进行测试之前,可以增加一个java类(如waitable)来实现线程阻塞机制。waitable利用了java语言中的wait和notify方法来实现,wait方法使得线程进入阻塞状态,notify方法则使线程重新进入执行状态,此外,wait方法允许指定一段时间作为参数,作为等待超时时间,恰好可以用来配置测试用例超时时间。同时,新增一个java类(如testrequestresult),其包含callback和waitable两个成员变量。若需要对某个异步接口进行测试,则在调用该异步接口之前,新建testrequestresult,设置异步回调callback,并新建waitable对象,使用waitable对象阻塞测试线程,这样测试线程就会一直“等待”异步接口回调,当该异步接口回调之后结束waitable对象,测试线程继续执行,进而简单方便地实现了对异步接口的测试。应用场景二:在对异步接口进行测试之前,增加一个类(如invocationfuture)作为异步接口的直接返回类型,invocationfuture的成员变量中包括一个回调callback,在异步接口执行完毕之后可以回调invocationfuture的callback。有了invocationfuture,可以设计异步接口验证方法,如checkresponse(invocationfuture,responsecode,callback)。其中的参数responsecode传入异步接口的预期返回码,参数callback为设置到invocationfuture的callback,同时checkreponse方法内部封装waitable方法,进而在执行checkreponse方法来测试异步接口时,也会通过waitable阻塞测试线程,当该异步接口回调之后结束waitable对象,使测试线程继续执行,同样能够方便地实现对异步接口的测试。示例性方法下面结合上述的应用场景,参考图1至图10来描述根据本发明示例性实施方式的异步接口的测试方法。图1示意性示出了根据本发明的一个实施例的异步接口的测试方法的流程图。参照图1所示,根据本发明的一个实施例的异步接口的测试方法,包括如下步骤:步骤s110,通过测试线程调用待测试的异步接口。在本发明的一个实施例中,异步接口一般可以分为“增”、“删”、“改”、“查”接口,分别实现“增”、“删”、“改”、“查”的操作,如增加一条消息、删除一条消息、修改内容、查询内容等。步骤s120,在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程。在本发明的一个实施例中,可以调用线程阻塞对象中的wait方法,以使所述测试线程进入阻塞状态。步骤s130,在阻塞所述测试线程的期间内,对所述异步接口进行测试断言。在本发明的一个实施例中,对异步接口进行测试断言即是确定异步接口的测试结果。步骤s140,在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一个实施例中,可以调用线程阻塞对象中的notify方法,以使所述测试线程重新进入执行状态。图1所示实施例的技术方案能够通过线程阻塞对象阻塞测试线程,以等待对异步接口的测试及断言,避免了现有的自动化测试方案在测试用例还未断言就已经执行结束的问题,同时也解决了异步接口测试困难的问题,实现了对异步接口的便捷测试,简化了对异步接口测试用例的复杂度,提高了测试开发效率。基于图1所示的通过线程阻塞对象实现对异步接口进行测试的方案,本发明提出了如下两种具体应用线程阻塞对象对异步接口进行测试的实施例:实施例一:在本发明的一个实施例中,如图2所示,在步骤s110之前,还包括:步骤s210,生成一测试结果类和线程阻塞类,将所述线程阻塞类作为所述测试结果类的成员变量。在本发明的一个实施例中,测试结果类与线程阻塞类可以是java类,如测试结果类可以是testrequestresult类,线程阻塞类可以是waitable类。步骤s220,实例化所述测试结果类,以得到测试结果对象和所述线程阻塞对象。在本发明的一个实施例中,实例化是指通过类创建对象的过程。步骤s230,将所述测试结果对象设置为所述异步接口的回调对象。图2所示实施例的技术方案可以通过测试结果类来实现对待测试异步接口的测试。基于图2所示实施例的技术方案,在本发明的一个实施例中,对异步接口进行测试断言包括:根据所述异步接口的回调结果,确定所述异步接口的实际返回码,或确定所述异步接口的实际返回码和返回数据;根据所述实际返回码和预期返回码,或根据所述实际返回码、所述返回数据和预期返回码,对所述异步接口进行测试断言。在该实施例中,对于“增”、“删”、“改”类的异步接口,可以直接根据实际返回码和预期返回码来进行测试断言;而对于“查”类的异步接口,不仅需要根据实际返回码和预期返回码来进行测试断言,还需要根据该接口的实际返回数据来进行测试断言。在本发明的一个实施例中,可以获取包含有预期返回码的自定义注解,进而通过解析自定义注解来获取预期返回码。该实施例的技术方案使得能够利用自定义注解来获取预期返回码,简化了测试代码的复杂度。在本发明的一个实施例中,可以在对异步接口进行测试的测试用例执行之前,获取测试用例中包含的自定义注解。该实施例的技术方案使得能够将预期返回码从测试用例中转移到注解中,进而能够简化测试用例。其中,测试用例是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。实施例二:在本发明的一个实施例中,如图3所示,在步骤s110之前,还包括:步骤s310,创建一调用结果对象,将所述调用结果对象作为所述异步接口的直接返回类型。在本发明的一个实施例中,调用结果对象可以是java对象,如invocationfuture对象。将调用结果对象作为异步接口的直接返回类型之后,可以根据调用结果对象来确定异步接口的返回值。步骤s320,以所述调用结果对象和预期返回码作为输入参数,构建异步接口验证方法,并在所述异步接口验证方法中封装线程阻塞对象。在本发明的实施例中,通过将调用结果对象和预期返回码作为输入参数来构建异步接口验证方法,使得只需将调用结果对象和预期返回码传入异步接口验证方法,即可实现对待测试异步接口的验证。步骤s330,执行所述异步接口验证方法。基于图3所示实施例的技术方案,在对异步接口进行测试断言时,可以将调用结果对象的值作为所述异步接口的实际返回码,根据所述实际返回码和所述预期返回码,对所述异步接口进行测试断言。这种方案适用于对“增”、“删”、“改”类的异步接口进行测试。在本发明的一个实施例中,为了对“查”类的异步接口进行测试,可以在上述的调用结果对象的成员变量中增加一回调对象,且异步接口回调时调用该回调对象,并且在构建所述异步接口验证方法时,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法。基于此,在进行测试时,可以将调用结果对象的值作为所述异步接口的实际返回码,将所述回调对象的值作为所述异步接口的返回数据,根据所述实际返回码、所述预期返回码和所述返回数据,对所述异步接口进行测试断言。此外,在本发明的一个实施例中,为了保证调用一次异步接口验证方法,以实现对异步接口的多次验证,可以生成回调对象数组和调用结果对象数组,且该回调对象数组中的回调对象与所述调用结果对象数组中的调用结果对象一一对应,进而将所述回调对象数组、所述调用结果对象数组和所述预期返回码作为输入参数,构建所述异步接口验证方法。这样可以通过数组的形式来实现一次调用多次验证的效果。基于前述的通过回调对象数组和调用结果对象数组构建异步接口验证方法的方案,来在本发明的一个实施例中,可以在根据每一对所述回调对象和所述调用结果对象进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。该实施例的技术方案可以保证在根据每一对回调对象和调用结果对象进行测试断言之后,再使测试线程继续执行,实现了在测试线程的阻塞期间对异步接口进行多次验证的效果。在本发明的一个实施例中,上述的异步接口验证方法所归属的类为基类的派生类,进而可以方便地通过继承基类来在测试用例中复用异步接口验证方法。在本发明的一个实施例中,可以获取包含有预期返回码的自定义注解,进而通过解析自定义注解来获取预期返回码。该实施例的技术方案使得能够利用自定义注解来获取预期返回码,简化了测试代码的复杂度。在本发明的一个实施例中,可以在对异步接口进行测试的测试用例执行之前,获取测试用例中包含的自定义注解。该实施例的技术方案使得能够将预期返回码从测试用例中转移到注解中,进而能够简化测试用例。其中,测试用例是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。基于上述实施例的技术方案,在本发明的一个实施例中还提出了如何生成测试报告的方案,具体如图4所示,包括如下步骤:步骤s410,在对异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的自定义注解,所述自定义注解中包含有用于生成测试报告的信息。在本发明的一个实施例中,用于生成测试报告的信息包括:待测试的异步端口、测试步骤、预期返回码等。步骤s420,解析所述自定义注解,以得到所述用于生成测试报告的信息。步骤s430,根据所述用于生成测试报告的信息和对所述异步接口进行测试断言的结果,生成测试报告。图4所示实施例的技术方案使得能够通过解析自定义注解来获取生成测试报告的信息,达到了将测试报告统计与测试脚本分离的目的,进而能够简化测试用例。以下结合图5至图10,以使用java语言编写测试用例脚本为例,对本发明实施例的技术方案的实现细节进行详细阐述。在自动化测试技术中,一种方式是直接使用androidjunitrunner(google官方提供的一种android程序单元测试工具)进行自动化测试,并使用java语言按照androidjunitrunner的规范和要求,按部就班地对每个接口编写测试用例脚本。同时,对每一个接口,构建正常、异常场景,分别调用接口并将返回结果与预期进行对比。但是这种方式由于没有对测试用例进行简化,因此会在前期测试用例脚本上付出巨大人力成本,主要表现在以下方面:1、接口从形式上分为同步接口和异步接口,其中大部分是异步接口,对于异步接口而言,测试用例需要在调用接口之后使测试线程休眠,等待接口回调之后进行断言,否则会跳过断言结束测试用例,达不到测试的目的。2、接口测试往往需要构建前置场景,比如测试发送消息接口,需要调用登录接口成功后,才能发送消息。再如测试“踢出群成员”接口,测试预备环境是存在一个群、一个群主、一个管理员和至少一个群成员,前置条件准备步骤为:a.成员需要首先创建一个群,并邀请至少两个成员;b.被邀请的成员登录并接受邀请入群;c.群主将其中一个成员设置为管理员操作,此时成员分布为一个群主、一个管理员、一个普通成员。3、sdk接口数量较多,每个接口要覆盖正常、异常场景。如果测试用例复杂,则需要付出巨大的人力成本。同样以测试“踢出群成员”接口为例,sdk只允许群主或管理员有权限进行操作,正常情况下是群主或管理员踢掉了一个群成员。异常情况比较多,比如:a.使用非群主/管理员去踢出群成员;b.使用群主/管理员踢掉一个不在本群里的用户;c.使用群主/管理员踢掉一个不存在的用户;d.使用管理员踢掉群主。4、没有生成接口测试报告。以上问题是使用androidjunitrunner进行接口自动化测试的关键问题。针对上述问题,本发明的实施例设计并实现了一种异步接口自动化测试方法,目的是解决异步接口测试困难的问题,并且简化测试用例脚本的复杂度,提高测试开发效率。具体包括以下几个部分:设计线程阻塞机制、设计接口验证方法、简化接口验证方法、优化批量验证接口、简化测试报告生成方法、封装公共方法。以下逐一进行说明:1、设计线程阻塞机制在本发明的一个实施例中,增加了一个java类waitable实现线程阻塞机制,线程阻塞是指暂停一个线程的执行以等待某个条件发生(如某资源就绪)。waitable利用了java语言中的wait方法和notify方法来实现,wait方法使得线程进入阻塞状态,notify方法则使线程重新进入执行状态。此外,wait方法允许指定一段时间作为参数,作为等待超时时间,恰好可以用来配置测试用例超时时间。同时,新增java类testrequestresult继承异步接口回调callback,并添加waitable作为testrequestresult的成员变量。在调用某异步接口之前,新建testrequestresult作为此接口callback,testrequestresult实例化时新建waitable对象,并使用waitable阻塞线程,这样测试线程就会一直“等待”,当异步接口callback回调之后结束waitable,进而测试线程会继续执行。此过程事实上将异步接口调用转换成了同步接口调用。由于异步接口回调函数在主线程(即androidui线程)执行,此时存在三条线程,waitable运行流程如图5所示,包括如下步骤:步骤s501,测试线程实例化testrequestresult和waitable。步骤s502,调用异步接口,设置testrequestresult为异步接口的callback。步骤s503,通过异步线程使异步接口执行。步骤s504,在调用异步线程之后,调用waitable的wait方法使测试线程进入阻塞状态。步骤s505,异步接口执行完毕之后,异步回调线程回调testrequestresult。步骤s506,基于回调结果进行测试断言。步骤s507,调用waitable的notify方法使测试线程重新进入运行状态。在上述实施例中,利用testrequestresult和waitable,可以解决异步接口测试问题,同样也可以将异步方法转换成同步方法,以便于在构建接口测试前置环境中发挥作用。在本发明的上述实施例中,是通过waitable的wait方法和notify方法进行线程的阻塞和恢复。在本发明的另一个实施例中,还可以调用java的sleep方法,将当前线程休眠一定时间,例如200ms,之后检查异步接口是否回调,如果没有回调则重复这个过程,直到异步接口回调为止。2、设计接口验证方法在上述实施例中,使用waitable将异步转换成同步接口,虽然能够对异步接口进行测试,但是在大量的测试用例中重复使用testrequestresult仍不够简便。如果有一种验证方法,只需要将接口调用和预期返回码、回调callback(为了在回调中验证“查”接口的返回值)等作为参数传递给此方法即可实现测试,那么在省掉testrequestresult后会大大简化测试用例。由于异步接口的形式如:voidquerymessage(callback),直接返回往往为void,无法作为方法参数,因此增加一个类invocationfuture作为异步方法直接返回类型,invocationfuture的成员变量包括一个回调callback,在异步接口执行完毕之后回调invocationfuture的callback。这个过程之后,voidquerymessage(callback)被封装为invocationfuturequerymessage()。封装逻辑整理如下:新建invocationfuture对象;调用真正的异步接口,并在异步接口回调中,调用invocationfuture的callback;返回invocationfuture。有了invocationfuture,利用java语言的继承特性,设计java基类basetestcase,设计异步接口验证方法checkresponse(invocationfuture,responsecode,callback),将该方法设置为继承基类,这样可以在测试用例中复用该方法。其中,responsecode传入接口预期返回码,callback为设置到invocationfuture(非必须)的callback。checkreponse方法内部处理封装waitable,使得测试用例中专注自身的逻辑。其中,checkreponse方法的执行过程如图6所示,包括如下步骤:步骤s601,执行checkresponse(invocationfuture,responsecode,callback)方法。步骤s602,将checkresponse方法中的callback传递给invocationfuture。步骤s603,调用异步接口执行。步骤s604,实例化waitable,同时调用waitable的wait方法使测试线程进入阻塞状态。步骤s605,异步接口执行完毕之后,回调上述的callback。步骤s606,基于回调结果(callback和实际返回码)进行测试断言。步骤s607,调用waitable的notify方法使测试线程重新进入运行状态。基于前述的checkresponse方法,测试用例的执行逻辑如图7所示,包括如下步骤:步骤s701,测试线程调用异步接口,返回invocationfuture。步骤s702,新建callback,设置为checkresponse方法的callback。步骤s703,执行checkresponse(invocationfuture,responsecode,callback)方法对异步接口进行检验。如上所述,通过checkresponse方法,可以使测试用例的逻辑明显简洁易懂,达到了简化测试用例的目的。在本发明的上述实施例中,是通过checkresponse方法直接验证异步接口,而在本发明的另一个实施例中,还可以将异步接口转换成同步接口,并将异步回调数据转换成同步接口的返回值,进而通过返回值进行验证和断言。3、简化接口验证方法在本发明的实施例中,由于大多数异步接口是“增”、“删”、“改”操作,只需要验证实际返回码,无须callback,因此有必要着手简化checkresponse方法。java注解是一种代码级别的说明,方法(函数)级别的注解和类级别的注解运用最为广泛,在使用时类似给方法添加“注释”一样,显著的优点是注解与方法内部的代码逻辑隔离。因此,在本发明的一个实施例中,可以添加自定义方法级别注解@testmodel,而自定义注解能自由定义注解参数,进而可以将接口的预期返回码作为注解参数,目的是为了将预期返回码从测试用例转移到注解中,进而可以在一定程度上简化测试用例。在定义了@testmodel注解之后,关键问题是在适当的时机解析注解,从中获取到注解参数(此处是预期返回码),否则将无法利用注解。在本发明的一个实施例中,可以利用junit4的rule特性,在测试用例执行之前,动态获取将要运行的测试信息,包括测试类、测试方法、测试方法注解等信息,此时便可获取注解中预设的返回码。此时测试用例脚本执行流程如下所示:a.利用rule特性,在执行测试用例之前将其“拦截”;b.从“拦截”的测试脚本方法中,获取注解信息@testmodel;c.从上一步获取到的注解中,解析注解参数,即预期返回码;d.开始执行测试脚本;e.比较测试脚本执行结束后的实际返回码与注解中设置的预期返回码并进行测试断言。经过上述过程,可以将预期返回码从checkresponse参数转移到注解中,对于“增”、“删”、“改”接口的验证逻辑,由于不需要callback验证,因此验证流程则进一步优化为如图8所示,包括如下步骤:步骤s801,测试线程调用异步接口,返回invocationfuture。步骤s802,执行checkresponse(invocationfuture,responsecode,callback)方法对异步接口进行检验。如上所述,通过将预期返回码转移到注解中,可以进一步简化测试用例。4、优化批量验证接口由于单个测试用例中往往不仅仅只调用一次接口,例如测试发送消息接口时,由于消息类型包含文本、图片、音频、视频等多种类型,因此需要在一个测试用例中多次验证同一个接口。在本发明的一个实施例中,为了实现对接口的多次验证,可以重载checkresponse方法,增加参数类型为invocationfuture数组和callback数组,数组元素invocationfuture和callback一一对应。同时,扩展waitbale,在全部接口调用之后调用wait阻塞线程,等待全部接口回调之后再调用notify恢复线程,进而可以实现调用一次checkresponse达到了验证多次接口的效果。5、简化测试报告生成方法在本发明的一个实施例中,可以利用前述的自定义注解@testmodel简化测试报告的生成过程。具体来说,传统的测试报告生成方法是,在测试用中,将本条测试用例需要记入测试报告的信息写入缓存,例如被测哪个接口、测试步骤、目标返回码、实际返回码等等,在所有的测试用例执行完毕后,依据缓存信息计算测试通过率、接口覆盖率等信息,最后和缓存一起写入测试报告文件中。这样的缺点是每个测试用例中加入测试报告逻辑,增加了测试用例工作量。因此选择将测试报告统计信息放入@testmodel中,并且在执行测试用例之前将其“拦截”,从“拦截”的测试脚本方法中,获取注解信息进行解析,进而可以达到测试报告统计与测试脚本分离的目的,从而简化测试用例。生成的测试报告效果可以如图9和图10所示。6、封装公共方法。接口测试常常需要构建前置场景,不同的接口需要的前置条件常常是相同的,例如设置群管理员接口和发送群消息接口,都需要存在一个群以及群成员。因此在本发明的一个实施例中,可以将构建步骤拆分,并封装为公共方法。例如createteam()创建一个群,jointeam(teamid)加入一个群等,进而可以在测试脚本中,复用这些封装好的方法,从而在一定程度上减少了工作量。本发明上述实施例的技术方案创建了线程阻塞机制waitable,利用waitable将异步接口转换为同步接口,解决了异步接口测试困难的问题;同时创建了异步接口验证方法checkresponse,将验证逻辑与测试脚本分离,在测试用例中调用接口并将预期结果或者callback传入checkresponse即可,大大简化了测试脚本逻辑。同时,将预期返回码responsecode从测试用例脚本中转移到自定义注解中,进一步简化了checkresponse方法,对于不需要callback验证的接口(如“查”接口),在测试用例中只需将调用接口返回invocationfuture传入checkresponse即可完成验证,进一步简化了测试用例。此外,本发明上述实施例的技术方案可以将测试报告统计信息收集过程从测试脚本转移到注解中,简化了测试用例。并且创建了丰富的公共方法,利用这些公共方法,在准备测试前置环境时达到了命令式编程的目的,每一步只需要一行代码即可实现,步骤清晰、简洁易懂。示例性介质在介绍了本发明示例性实施方式的方法之后,接下来,对本发明示例性实施方式的介质进行说明。在一些可能的实施方式中,本发明的各个方面还可以实现为一种介质,其上存储有程序代码,当所述程序代码被设备的处理器执行时用于实现本说明书上述“示例性方法”部分中描述的根据本发明各种示例性实施方式的异步接口的测试方法中的步骤。具体地,所述设备的处理器执行所述程序代码时用于实现如下步骤:通过测试线程调用待测试的异步接口;在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程;在阻塞所述测试线程的期间内,对所述异步接口进行测试断言;在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时还用于实现如下步骤:在通过测试线程调用待测试的异步接口之前,生成一测试结果类和线程阻塞类,将所述线程阻塞类作为所述测试结果类的成员变量;实例化所述测试结果类,以得到测试结果对象和所述线程阻塞对象;将所述测试结果对象设置为所述异步接口的回调对象。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:根据所述异步接口的回调结果,确定所述异步接口的实际返回码,或确定所述异步接口的实际返回码和返回数据;根据所述实际返回码和预期返回码,或根据所述实际返回码、所述返回数据和预期返回码,对所述异步接口进行测试断言。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时还用于实现如下步骤:在通过测试线程调用待测试的异步接口之前,创建一调用结果对象,将所述调用结果对象作为所述异步接口的直接返回类型;以所述调用结果对象和预期返回码作为输入参数,构建异步接口验证方法,并在所述异步接口验证方法中封装所述线程阻塞对象;执行所述异步接口验证方法。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:将所述调用结果对象的值作为所述异步接口的实际返回码,根据所述实际返回码和所述预期返回码,对所述异步接口进行测试断言。在本发明的一些实施方式中,所述调用结果对象的成员变量包含一回调对象,所述异步接口回调时调用所述回调对象;所述设备的处理器执行所述程序代码时还用于实现如下步骤:在构建所述异步接口验证方法时,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:将所述调用结果对象的值作为所述异步接口的实际返回码,将所述回调对象的值作为所述异步接口的返回数据,根据所述实际返回码、所述预期返回码和所述返回数据,对所述异步接口进行测试断言。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:生成回调对象数组和调用结果对象数组,所述回调对象数组中的回调对象与所述调用结果对象数组中的调用结果对象一一对应;将所述回调对象数组、所述调用结果对象数组和所述预期返回码作为输入参数,构建所述异步接口验证方法。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:在根据每一对所述回调对象和所述调用结果对象进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述异步接口验证方法所归属的类为基类的派生类。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时还用于实现如下步骤:获取包含有所述预期返回码的自定义注解;解析所述自定义注解,以获取所述预期返回码。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的所述自定义注解。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时还用于实现如下步骤:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的自定义注解,所述自定义注解中包含有用于生成测试报告的信息;解析所述自定义注解,以得到所述用于生成测试报告的信息;根据所述用于生成测试报告的信息和对所述异步接口进行测试断言的结果,生成测试报告。在本发明的一些实施例中,基于前述方案,所述用于生成测试报告的信息包括:待测试的异步端口、测试步骤、预期返回码。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:调用所述线程阻塞对象中的wait方法,以使所述测试线程进入阻塞状态。在本发明的一些实施方式中,所述设备的处理器执行所述程序代码时用于实现如下步骤:调用所述线程阻塞对象中的notify方法,以使所述测试线程重新进入执行状态。需要说明的是:上述的介质可以是可读信号介质或者可读存储介质。可读存储介质例如可以是但不限于:电、磁、光、电磁、红外线、或半导体的系统、装置或器件,或者任意以上的组合。可读存储介质的更具体的例子(非穷举的列表)包括:具有一个或多个导线的电连接、便携式盘、硬盘、随机存取存储器(ram)、只读存储器(rom)、可擦式可编程只读存储器(eprom或闪存)、光纤、便携式紧凑盘只读存储器(cd-rom)、光存储器件、磁存储器件、或者上述的任意合适的组合。可读信号介质可以包括在基带中或者作为载波一部分传播的数据信号,其中承载了可读程序代码。这种传播的数据信号可以采用多种形式,包括但不限于:电磁信号、光信号或上述的任意合适的组合。可读信号介质还可以是可读存储介质以外的任何可读介质,该可读介质可以发送、传播或者传输用于由指令执行系统、装置或者器件使用或者与其结合使用的程序。可读介质上包含的程序代码可以用任何适当的介质传输,包括但不限于:无线、有线、光缆、rf等,或者上述的任意合适的组合。可以以一种或多种程序设计语言的任意组合来编写用于执行本发明操作的程序代码,所述程序设计语言包括面向对象的程序设计语言—诸如java、c++等,还包括常规的过程式程序设计语言—诸如“c”语言或类似的程序设计语言。程序代码可以完全地在用户计算设备上执行、部分在用户计算设备上部分在远程计算设备上执行、或者完全在远程计算设备或服务器上执行。在涉及远程计算设备的情形中,远程计算设备可以通过任意种类的网络——包括局域网(lan)或广域网(wan)—连接到用户计算设备,或者,可以连接到外部计算设备(例如利用因特网服务提供商来通过因特网连接)。示例性装置在介绍了本发明示例性实施方式的介质之后,接下来,参考图11对本发明示例性实施方式的异步接口的测试装置进行说明。图11示意性示出了根据本发明的实施例的异步接口的测试装置的框图。参照图11所示,根据本发明的实施例的异步接口的测试装置1100,包括:调用单元1101、阻塞单元1102、处理单元1103和恢复单元1104。其中,调用单元1101用于通过测试线程调用待测试的异步接口;阻塞单元1102用于在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程;处理单元1103用于在阻塞所述测试线程的期间内,对所述异步接口进行测试断言;恢复单元1104用于在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述的装置1100还包括:第一生成单元1105,用于在通过测试线程调用待测试的异步接口之前,生成一测试结果类和线程阻塞类,将所述线程阻塞类作为所述测试结果类的成员变量;实例化单元1106,用于实例化所述测试结果类,以得到测试结果对象和所述线程阻塞对象,并将所述测试结果对象设置为所述异步接口的回调对象。在本发明的一些实施例中,基于前述方案,所述处理单元1103配置为:根据所述异步接口的回调结果,确定所述异步接口的实际返回码,或确定所述异步接口的实际返回码和返回数据;根据所述实际返回码和预期返回码,或根据所述实际返回码、所述返回数据和预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述的装置1100还包括:创建单元1107,用于在通过测试线程调用待测试的异步接口之前,创建一调用结果对象,将所述调用结果对象作为所述异步接口的直接返回类型;构建单元1108,用于以所述调用结果对象和预期返回码作为输入参数,构建异步接口验证方法,并在所述异步接口验证方法中封装所述线程阻塞对象;执行单元1109,用于执行所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述处理单元1103配置为:将所述调用结果对象的值作为所述异步接口的实际返回码,根据所述实际返回码和所述预期返回码,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述调用结果对象的成员变量包含一回调对象,所述异步接口回调时调用所述回调对象;所述构建单元1108用于:在构建所述异步接口验证方法时,将所述回调对象、所述调用结果对象和所述预期返回码共同作为输入参数来构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述处理单元1103配置为:将所述调用结果对象的值作为所述异步接口的实际返回码,将所述回调对象的值作为所述异步接口的返回数据,根据所述实际返回码、所述预期返回码和所述返回数据,对所述异步接口进行测试断言。在本发明的一些实施例中,基于前述方案,所述构建单元1108配置为:生成回调对象数组和调用结果对象数组,所述回调对象数组中的回调对象与所述调用结果对象数组中的调用结果对象一一对应;将所述回调对象数组、所述调用结果对象数组和所述预期返回码作为输入参数,构建所述异步接口验证方法。在本发明的一些实施例中,基于前述方案,所述恢复单元1104配置为:在根据每一对所述回调对象和所述调用结果对象进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。在本发明的一些实施例中,基于前述方案,所述异步接口验证方法所归属的类为基类的派生类。在本发明的一些实施例中,基于前述方案,所述的装置1100还包括:第一获取单元1110,用于获取包含有所述预期返回码的自定义注解;第一解析单元1111,用于解析所述自定义注解,以获取所述预期返回码。在本发明的一些实施例中,基于前述方案,所述第一获取单元1110配置为:在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的所述自定义注解。在本发明的一些实施例中,基于前述方案,所述的装置1100还包括:第二获取单元1112,用于在对所述异步接口进行测试的测试用例执行之前,获取所述测试用例中包含的自定义注解,所述自定义注解中包含有用于生成测试报告的信息;第二解析单元1113,用于解析所述自定义注解,以得到所述用于生成测试报告的信息;第二生成单元1114,用于根据所述用于生成测试报告的信息和对所述异步接口进行测试断言的结果,生成测试报告。在本发明的一些实施例中,基于前述方案,所述用于生成测试报告的信息包括:待测试的异步端口、测试步骤、预期返回码。在本发明的一些实施例中,基于前述方案,所述阻塞单元1102配置为:调用所述线程阻塞对象中的wait方法,以使所述测试线程进入阻塞状态。在本发明的一些实施例中,基于前述方案,所述恢复单元1104配置为:调用所述线程阻塞对象中的notify方法,以使所述测试线程重新进入执行状态。示例性计算设备在介绍了本发明示例性实施方式的方法、介质和装置之后,接下来,介绍根据本发明的另一示例性实施方式的计算设备。所属
技术领域
:的技术人员能够理解,本发明的各个方面可以实现为系统、方法或程序产品。因此,本发明的各个方面可以具体实现为以下形式,即:完全的硬件实施方式、完全的软件实施方式(包括固件、微代码等),或硬件和软件方面结合的实施方式,这里可以统称为“电路”、“模块”或“系统”。在一些可能的实施方式中,根据本发明实施方式的计算设备可以至少包括至少一个处理器、以及至少一个存储器。其中,所述存储器存储有程序代码,当所述程序代码被所述处理器执行时,使得所述处理器执行本说明书上述“示例性方法”部分中描述的根据本发明各种示例性实施方式的异步接口的测试方法中的步骤。例如,所述处理器可以执行如图1中所示的步骤s110,通过测试线程调用待测试的异步接口;步骤s120,在调用所述异步接口之后,基于线程阻塞对象阻塞所述测试线程;步骤s130,在阻塞所述测试线程的期间内,对所述异步接口进行测试断言;步骤s140,在对所述异步接口进行测试断言之后,基于所述线程阻塞对象使所述测试线程继续执行。又如,所述处理器也可以执行如图2至图8中所示的步骤。应当注意,尽管在上文详细描述中提及了异步接口的测试装置的若干单元或子单元,但是这种划分仅仅是示例性的,并非是强制性的。实际上,根据本发明的实施方式,上文描述的两个或更多模块或单元的特征和功能可以在一个模块或单元中具体化。反之,上文描述的一个模块或单元的特征和功能可以进一步划分为由多个模块或单元来具体化。此外,尽管在附图中以特定顺序描述了本发明方法的操作,但是,这并非要求或者暗示必须按照该特定顺序来执行这些操作,或是必须执行全部所示的操作才能实现期望的结果。附加地或备选地,可以省略某些步骤,将多个步骤合并为一个步骤执行,和/或将一个步骤分解为多个步骤执行。虽然已经参考若干具体实施方式描述了本发明的精神和原理,但是应该理解,本发明并不限于所发明的具体实施方式,对各方面的划分也不意味着这些方面中的特征不能组合以进行受益,这种划分仅是为了表述的方便。本发明旨在涵盖所附权利要求的精神和范围内所包括的各种修改和等同布置。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1