软件测试应用技术(3) -- 软件评测师(十六)
事件驱动架构,简称EDA,是常用的架构范式中的一种,其关注事件的产生、识别、处理、响应。对于事件驱动架构系统的测试应特别注意其业务逻辑处理上的异步特性导致的缺陷和事件队列处理中可能存在的全局性缺陷。事件驱动由事件来驱动整个系统。事件的来源可以是内部的或者外部的,也可能来自软件层面或硬件层面。(1)事件驱动架构的一般范式如下:1)事件(通知):由于内/外事件引发/触发/产生的特殊的“消息”。2)事件
5 事件驱动架构软件测试
5.1 事件驱动架构软件测试概述
事件驱动架构,简称EDA,是常用的架构范式中的一种,其关注事件的产生、识别、处理、响应。对于事件驱动架构系统的测试应特别注意其业务逻辑处理上的异步特性导致的缺陷和事件队列处理中可能存在的全局性缺陷。事件驱动由事件来驱动整个系统。事件的来源可以是内部的或者外部的,也可能来自软件层面或硬件层面。
(1)事件驱动架构的一般范式如下:
1)事件(通知):由于内/外事件引发/触发/产生的特殊的“消息”。
2)事件队列:一组数据结构和对于的处理逻辑,用于接收缓存接收到的事件(通知)。此环节引入了“异步”处理的特性,并且将事件与事件的处理解耦。同时事件队列也带来了处理顺序、优先级、缓存溢出等复杂的处理。
3)事件分发器:对事件进行预处理,分门别类地将事件转发到对其有“兴趣”的处理逻辑中。有“事件流”式处理和“注册/发布”式处理两种不同的实现方式。

4)事件通道:分发器将事件通知通过事件通道分发到事件处理逻辑。
5)事件处理逻辑:在这部分模块中实现具体业务逻辑的模块。它是架构中最复杂和最贴近业务需求的部分。有时可将这部分进一步通过状态机模型来实现。
(2)事件驱动架构的优点和缺点如下:
1)优点:擅长解决工程领域中以交互为主的问题。事件与事件处理逻辑、事件处理逻辑之间都得到了充分的解耦,从而使得软件易于扩展新的功能,还改善了软件的可维护性和可移植性,并且使得事件的分布式处理变得可能。交互时的响应性能较好。
2)缺点:事件驱动架构的实现是异步编程,开发相对复杂,与事件处理相关的缺陷也非常常见,同时在实践中,此类缺陷导致的失效往往比较难以复现和定位。
5.2 事件驱动架构的质量特性
(1)功能性:事件驱动的架构适合那些功能上涉及交互比较多甚至交互为主要内容的业务领域。对于功能质量属性应集中考虑是否功能都落实到了架构中,是否功能的交互要求在架构中得到了合理的体现,对于架构更多地是非功能属性的考量。
(2)可靠性:事件驱动架构与可靠性及其子质量特性密切相关。在大多数情况下,正确实现的事件驱动架构虽然与成熟性、可用性这两个子特性相关,但相对而言更容易出现问题的是容错性和易恢复性。
(3)性能效率:事件驱动架构同样与性能效率及其子质量特性密切相关。性能和效率的3个子质量特性都受到事件驱动架构各个环节的影响。
(4)易用性:事件驱动架构并不直接与系统的用户打交道,易用性质量特性与一般的系统使用的用户基本无关。
(5)信息安全性:常见的与信息安全性质量特性相关的缺陷集中在接口的处理上。事件驱动架构实现的系统的信息安全问题主要集中在系统对外接口即事件通知的发送和接收环节,并且需要特别注意的是并非所有的系统都有相同的信息安全要求。根据业务需要考虑信息安全的要求是必须的。即一个系统可能有加密和完整性的要求,但不一定有抵抗赖和可核查性的要求。
(6)兼容性:兼容性相关的质量要求主要与具体的业务和运行环境相关。对于事件驱动架构而言,与外部系统发生联系的组件更容易在兼容性上存在缺陷。
(7)维护性:事件驱动架构本身在支持可维护性上提供了很好的模块化范式。只要很好地遵循了事件驱动架构的架构范式要求,在事件驱动框架(甚至引擎)下编程,一般很少出现维护性问题。
(8)可移植性:事件驱动架构也通过架构范式提供了很好的可移植性。模块化的事件收发、事件队列、事件分发器和事件处理机制支持的架构本身可以方便替换和移植。
5.3 事件驱动架构的测试策略
事件驱动架构范式的核心思想是将业务功能的处理抽象为事件和事件的响应处理。故此在事件驱动架构的各个组件中,大部分组件与具体业务无关,可以看作是一个独立的具备固有功能的软件系统,业务逻辑仅存在于少量组件中,并且互相解耦。与具体业务相关的组件有:事件通知的编码解码。
基于事件驱动架构开发的软件系统,通常最基本的测试策略就是将事件驱动架构的实现逻辑(事件驱动架构组件)与业务逻辑(事件的处理)分开测试。对于事件驱动架构系统的测试策略,可以分别考虑事件驱动架构本身的测试策略和建立在其之上的业务系统的测试策略,如下:
(1)事件驱动本身的测试策略:
- 单元测试:对各个组件分别安装各自的单元测试
- 集成测试:在单元测试通过的基础上,应对事件驱动架构的实现进行集成测试。
(2)业务系统的业务逻辑测试策略:
- 单元测试:主要可以集中在事件处理逻辑中。
- 集成测试:覆盖优先级相关的业务逻辑。
- 系统测试:采用基于规格说明的测试技术来涉及测试用例,通过用户界面或系统接口来实现测试执行。
6 微内核架构软件测试
6.1 概述
微内核架构,又称微插件架构,指的是软件的内核相对较小,主要功能和业务逻辑都通过插件实现。内核通常只包含系统运行的最小功能,插件相互独立,插件间尽量不通信,避免出现互相依赖的问题。微内核架构主要考虑两个方面:核心系统(内核系统)和插件模块。微内核架构模式如下图所示:

微内核架构的特点是模块高度独立,可移植。
(1)微内核架构模式的核心如下:
1)基本服务封装到内核
2)插件模块负责整合某个特定领域的抽象,微内核负责通用的功能抽象。
3)应用程序、服务器通过基于“事件”的微内核通信,用来沟通各个不同的模块。
(2)微内核架构涉及的三个关键点如下:
1)插件管理:核心系统提供一个服务来响应插件的注册请求,最终将当前系统的所有插件信息(插件标识、类别、启动方式等)保存起来。存储方式可以选择配置文件存储或数据表存储等。
2)插件连接:插件之间的通信需要通过核心系统作为桥梁,故核心系统除去注册表机制外,还需要提供类似操作系统总线之间的通信机制。
3)微内核架构的优点:
- 整体灵活性高,能够快速响应不断变化的环境。
- 易于部署,因为功能之间是隔离的,插件可以独立地加载和卸载。
- 可定制性高,适应不同的开发需求。
- 可测试性高,插件模块可以单独测试,能够非常简单地被核心系统模拟出来进行演示,或者在对核心系统很小影响甚至没有影响的情况下对一个特性进行原型展示。
- 性能高。
4)微内核架构的缺点:
- 通信效率低,插件通过内核实现间接通信,需要更多开销。
- 开发难度较高,微内核架构需要涉及,因此实现起来比较复杂。
- 通信规约,丰富的插件通信连接方法。
- 版本控制复杂。
6.2 微内核架构的质量特性
(1)功能性:功能性部分的测试点为微内核软件或系统安装与卸载插件、插件的具体功能使用测试,各个部分又分成若干个具体的测试项。采用黑盒测试方法,主要通过微内核软件或系统和插件提供的图形化界面对功能特性进行测试。
(2)信息安全性:首先,对插件的安全性进行评估,查看是否含有病毒、上传用户数据、窃取用户隐私等;其次,对其漏洞进行扫描分析,查看是否存在安全漏洞可被黑客调用。
(3)可靠性:对集成插件后的应用进行测试,查看插件和整体应用的稳定性,是否会出现集成后崩溃、闪退、兼容性降低、效率变低等问题。
(4)易用性:体现为易操作、易理解,有友好的向导,方便用户对已加载的插件进行管理或配置插件。
6.3 微内核架构的测试策略
在确定微内核架构的测试范围时,由需求文档确认本次需求的目标。微内核架构的测试策略如下:
(1)单元测试:主要是对各个插件模块进行测试,保证插件功能可以正常使用。
(2)集成测试:在单元测试的基础上,将内核与插件模块按照设计要求组装成为子系统或系统进行测试,主要是测试内核与插件、插件与插件之间是否存在问题。
(3)系统测试:将经过集成测试的软件系统,作为计算机系统的一部分,与系统中的其他部分结合起来,在实际运行环境下对软件系统进行一系列严格有效的测试,以求发现软件潜在的问题,保证系统的正常运行。当功能测试完成后,再考虑兼容性测试、性能测试。
7 分布式架构软件测试
7.1 概述
分布式架构的特点如下:
(1)系统内部由多个独立的计算机组成
(2)系统外部呈现为单个的系统
分布式架构的基本组件:
(1)分布式业务框架。
(2)分布式缓存和管理组件
(3)分布式消息组件
(4)分布式数据库
(5)分布式文件系统
分布式架构的优点如下:
(1)支持大量并发用户:最核心的优势,是采用分布式架构的主要原因。
(2)容错和灾备能力:分布式架构自然带来的优势。
(3)可灵活扩展:遵循正确的设计原则时能得到。
分布式架构软件的缺点如下:
(1)高维护成本:由复杂性带来的
(2)数据/事务处理上的一致性难题:由架构组件和设计规范来尽量避免,但仍然是最容易出现缺陷的场景。
(3)逻辑耦合强,定位问题困难:当遵循合适的设计原则时能在一定程度上降低。
7.2 质量特性
(1)数据一致性相关:对数据一致性的牺牲可能导致业务功能相关的缺陷。但数据一致性与高可用性的平衡设计不足,多度偏向数据一致性的话,可能会影响到分布式架构软件系统整体上的可靠性,对系统性能和容量造成影响。
(2)事务处理相关:在分布式架构软件系统中,通常有嵌套式事务和分布式事务两种基本的事务实现方式。嵌套式事务能较好地保证系统的可靠性但容易导致性能问题,分布式事务在提供较好的性能和扩展性时带来了稳定性较差的副作用。可以采取以下措施来应对:
- 对由嵌套式事务模式实现的业务逻辑针对性地设计性能测试和压力测试。
- 对由分布式事务模式实现的业务逻辑进行容错性测试。
(3)并发和互斥相关:对于高并发的技术问题其可能的影响如下:
1)数据的错误读写出现在业务直接相关的区域从而直接影响到业务功能的功能特性。
2)数据的错误读写出现在服务软件的逻辑区域,比如循环变量、内存堆栈,从而影响到服务的可靠性。
3)为确保不出现数据的读写错误,过度扩大临界区范围的软件设计可能导致并发性能的下降。
可采取以下策略和技术来应对:
- 分层的测试策略
- 尽早地开展测试获得,参与设计评审
- 结合软件设计实现并发与互斥的逻辑,通过场景法、边界值法、状态转移法等测试设计方法,针对软件设计的弱点设计测试用例覆盖。
- 单元测试中,应针对具体算法逻辑、业务逻辑,进行代码逻辑覆盖和功能覆盖。
(4)远过程调用和通信相关:远过程调用会带来额外的开销和通信上的延迟,对服务或模块不恰当的切分反而可能导致性能的下降。当远过程调用或通信跨地域或跨因特网时,由于因特网本身对信息安全无保障机制,故此自然带来了信息安全的风险。若远过程调用的是另外一台计算机上的资源,故此当远程计算机出现错误时,本地模块不应随之崩溃,这样的要求就是容错性要求。可采取以下策略和技术应对:
- 强调集成测试
- 在各个集成层面上进行性能测试
- 容错的场景设计覆盖和灾备演练可以在分布式架构系统的各个集成粒度上进行。
- 对于承载在因特网而非局域网上的远过程调用和通信,应组织专门的信息安全测试。
7.3 分布式架构软件测试常见的质量目标
| 质量目标 |
互联网系统 (云服务) |
对等网络 (区块链) |
并行计算 | 大数据和机器学习 |
| 容量 | 适应业务量 | 要求高,适应大量的交易和业务 | 要求不高,计算密集 | 对数据存储和处理要求较高,对并发容量要求较低 |
| 容错 |
要求高,甚至在涉及经济和安全的系统中要求极高 |
要求不高,系统内置容错的功能,对于不能容错的情况也可以接受 | 要求不高,计算密集,不对功能的容错有高的要求 | 要求不高,能完成计算和学习目标即可 |
| 响应速度 | 要求极高,是业务的关键指标 | 要求不高,批量处理可允许较大的延时 | 要求不高,批量处理允许较大延时 | 要求不高,机器学习和大数据统计都是计算密集 |
| 弹性 | 要求较高,随业务量的变化可能每天都要变化(伸缩) | 要求较高,但包含在系统功能内,自动地进行伸缩 | 要求不高,一般预留必要的计算和存储资源 | 要求不高,一般预留必要的计算和存储资源 |
7.4 测试策略
(1)单元测试:对单个服务(或子系统)进行其对应的单元测试或子系统测试。通常分布式架构系统内模块的接口需要进行接口测试。这样的接口测试应覆盖功能、性能、稳定性和信息安全这些质量特性。
(2)集成测试:将多个服务集成后进行(系统)集成测试。一般子系统集成阶段是围绕单一业务进行的测试,所以在这个阶段进行性能和容错性测试能为后续更大规模集成打好基础。在互联网系统测试中经常提到的“全链路压测”往往在子系统集成或系统集成的层面上进行。
(3)系统测试:对整个系统进行完整的系统测试。一般上线进入生成环境前还需要结合终端应用进行端到端的测试、验收测试来确保上线的质量。
8 面向对象软件测试
面向对象的软件测试分为以下几种:
(1)面向对象分析的测试:简称OOA测试。可划分为以下5个方面:
1)对认定的对象的测试。
2)对认定的结构的测试。
3)对认定的主题的测试。
4)对定义的属性和实例关联的测试。属性是用来描述对象或结构所反映的实例的特性。而实例关联是反映实例集合间的映射关系。
5)对定义的服务和消息关联的测试:定义的服务就是定义的每一种对象和结构在问题空间所要求的行为。
(2)面向对象设计的测试:简称OOD测试。可划分为以下3个方面:
1)对认定的类的测试:OOD认定的类可以是OOA中认定的对象,也可以是对象所需要的服务的抽象,对象所具有的属性的抽象。
2)对构造的层次结构的测试:为了能够充分发挥面向对象的继承共享特性,OOD的类层次结构,通常基于OOA中产生的分类结构的原则来组织,着重体现父类和子类间的一般性和特殊性。
3)对类库的支持的测试:对类库的支持虽然也属于类层次结构的组织问题,但其强调的重点是再次软件开发的重用。
(3)面向对象编程的测试:简称OOP测试。面向对象程序所具有的继承、封装和多态的新特性,使得传统的测试策略不再完全使用。可分为以下2个方面:
1)数据成员是否满足数据封装的要求
2)类是否实现了要求的功能
(4)面向对象单元测试:一些传统的测试方法在面向对象的单元测试中都可以使用,但面向对象编程的特性使得对成员函数的测试,不完全等同于传统的函数或过程测试,尤其是继承特性和多态特性,使子类继承或过载的父类成员函数出现了传统测试中未遇见的问题。从以下两方面考虑:
1)继承的成员函数是否都不需要测试。对父类中已经测试过的成员函数,有两种情况需要在子类中重新测试:
- 继承的成员函数在子类中做了改动。
- 成员函数调用了改动过的成员函数的部分。
2)对父类的测试是否能照搬到子类:对具有包含多态的成员函数进行测试时,只需要在原有的测试分析和基础上增加对测试用例中输入数据的类型的考虑。
(5)面向对象集成测试:能够检测出相对独立的,单元测试无法检测出的,有些类相互之间作用时才会产生的错误。面向对象的集成测试可以分为两步进行:先进行静态测试,再进行动态测试。
(6)面向对象确认和系统测试:测试软件与系统其他部分配套运行的表现,以确保在系统各部分协调工作的环境下软件也能正常运行。
9 Web应用测试
一个典型的web系统的结构示意图如下:

(1)Web应用测试的分类如下:
1)按系统架构来分:可分为客户端的测试、服务器端的测试和网络上的测试。
2)按职能来分:可分为应用功能的测试、Web应用服务的测、安全系统的测试、数据库服务的测试。
3)按软件的质量特性来分:可分为功能测试、性能测试、安全性测试、兼容性测试和易用性测试。
4)按照开发阶段来分:可分为设计的测试、编码的测试和系统的测试。
(2)Web应用测试与其他软件测试的区别:
1)相同之处:测试内容基本相同,某些项目的测试方法基本相同,测试手段基本相同
2)不同之处:测试的重点不同,测试采用的工具不同,Web应用系统迫切需要新的测试技术和方法。
(3)Web应用的功能测试:常见的测试类型如下:
1)链接测试:
- 测试所有链接是否按指示的那样确实链接到了该链接的页面
- 测试所链接的页面是否存在
- 保证Web应用系统中没有孤立的页面
2)表单测试:
- 每个字段的验证
- 字段的默认值
- 表单中的输入
- 提交操作的完整性
3)内容测试:检验Web应用系统提供信息的正确性、准确性和相关性。
(4)Web应用的易用性测试:
1)界面测试:
- 页面中各元素布局的协调性
- 不同页面风格的统一性
- 用户在界面中操作的便利性
- 界面动态操作测试
2)辅助功能测试:主要包括使用说明、导航、站点地图、帮助等。
3)图形测试:
- 验证所有的图形是否有明确的用途
- 验证所有页面字体的颜色、风格是否一致
- 背景颜色与字体颜色和前景颜色是否相搭配
- 确认图片的大小和质量
(5)Web应用的负载压力测试:
1)负载测试:负载级别可以是某个时刻同时访问Web系统的用户数量,也可以是在线处理的数据量。负载测试应安排在Web系统发布以后,在实际的网络环境中进行测试。
2)压力测试:压力测试是测试系统的限制和故障恢复能力,即测试Web应用系统会不会崩溃,在什么情况下会崩溃。一般压力测试包含如下步骤:
- 确定交易执行响应时间
- Web系统能够承受的最大并发用户数量
- 模拟用户请求,以一个比较小的负载开始,逐渐增加模拟用户的数量,直到系统不能承受负载为止。
- 如果负载没有达到需求,那么应该优化这个Web程序。
(6)Web应用的兼容性测试:兼容性测试的着重点放在客户端,而客户端最重要的两个因素就是浏览器与操作系统,所以面向用户的兼容性测试可分为以下两个方面:平台的兼容性测试和浏览器的兼容性测试。
(7)Web应用的安全测试:一个完整的Web安全体系测试可以从部署与基础结构、输入验证、身份验证、授权、配置管理、敏感数据、会话管理、加密、参数操作、异常管理、审核和日志记录等几个方面入手。
1)SQL注入:通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意SQL命令,是黑客攻击数据库的一种常用方法。防止SQL注入的方法是:拼接SQL之前先对特殊符号进行转义,使其不作为SQL的功能符号即可。
2)XSS攻击:是一种经常出现在Web应用中的计算机安全漏洞,它允许恶意Web用户将代码植入到提供给其他用户使用的页面中。防止XSS攻击的方法:对输入进行过滤,对输出进行编码。
10 网络测试
(1)网络仿真技术:也称为网络模拟技术或者网络预测技术。是一种通过建立网络设备、链路和协议模型,并模拟网络流量的传输,从而获取网络设计或优化所需要的网络性能数据的仿真技术。
(2)网络测试对象:
1)网络平台:包括网络操作系统、文件服务器和工作站
2)应用层:是指应用程序的客户端、桌面操作系统和数据库软件等。
3)子系统:主要是指路由器、集线器、交换机和网桥
4)全局网路径:是整个网络系统中重要的点对点路径
(3)网络测试类型:
1)网络可靠性测试:使被测网络在较长时间内经受较大负载,通过监视网络中发生错误和出现故障,验证在高强度环境中网络系统的存活能力,也就是它的可靠性。
2)网络可接受性测试:在系统正式实施前的“试运行”,确保新系统能提供良好而稳定的性能。
3)网络瓶颈测试:为找到导致系统性能下降的瓶颈,需要进行网络瓶颈测试。
4)网络容量规划测试:进行该测试可检测当前网络中是否存在多余的容量空间。
5)网络升级测试:将硬件或软件的新版本与当前版本在性能、可靠性和功能等方面进行比较,同时验证产品升级对网络性能是否会有不良影响。
6)网络功能/特性测试:特性测试核实的是单个命令和应用程序功能,通常用较小的负载完成,关注的是用户界面、应用程序的操作以及用户与计算机之间的互操作。功能测试是面向网络的,核实的是应用程序的多用户特征和重负载下后台功能能够正确地执行,关注的是当多个用户使用应用程序时,网络和文件系统或数据库服务器之间的交互情况。
7)网络吞吐量测试:吞吐量测试检测的是每秒钟传输数据的字节数和数据报数,用于检测服务器、磁盘子系统、适配卡/驱动连接、网桥、路由器、集线器、交换器和通信连接。是标识网络设备、子网和全局网络运行性能的重要指标。
8)网络响应时间测试:检测系统完成一系列认为所需的时间
9)衰减测试:测试贯穿整个通信连接或者信道的信号衰减。
10)网络配置规模测试:利用应用程序响应时间测试和吞吐量测试的结果来确定网络组件的规模,还可以利用测试结果和测试者自身对网络体系结构和网络操作的知识,来调整特定的系统配置组件,改变网络的运行性能。
11)网络设备评估测试:产品评估主要是比较各个产品,例如:服务器、操作系统或应用程序的性能。
(4)网络测试指标:对网络设备和TCP/IP网络的检测主要包括的基本技术指标如下:
| 吞吐量 | 指被测试设备或被测试系统在不丢包的情况下,能够达到的最大包转发速率。 |
| 丢包率 | 通过测量由于缺少资源而未转发的包的比例来显示高负载状态下系统的性能。 |
| 延时 | 指测量系统在有负载条件下转发数据包所需的时间。 |
| 背靠背性能 | 指通过以最大帧速率发送突发传输流,并测量无包丢失时的最大突发长度(总包数量)来测试缓冲区容量。 |
(5)吞吐量的计算公式为 P=N*T*D, N:并发用户数量, T:每单位时间的在线事务数量, D:事务服务器每次处理的数据负载, P:系统的通信吞吐量。
(6)应用性能指(Apdex)的计算:根据实际响应实际结合Apdex阈值定义了如下3种不同的性能表现:
1)Satisfied(满意):应用响应时间低于或等于Apdex阈值,一般简称T
2)Tolerating(可容忍):应用响应时间大于T,但同时小于或等于4T
3)Frustrated(失望):应用响应时间大于4T,太慢了,用户可能放弃这个应用。
Apdex计算公式为:Apdex = (满意的样本数+可容忍的样本数/2)/总样本数。其中,总样本数 = 满意的样本数 +可容忍的样本数 +失望的样本数。
11 文档测试
软件文档的分类结构如下图所示:

(1)用户文档的内容:当用户文档仅包含一个Readme文件时,文档的测试只需要对其进行拼写检查,确认其中涉及到的技术准确无误。但随着技术的进步和市场的规范,用户文档的范围也越来越大了,以下这些都可以算是用户文档,但并不是每一个软件都必须具有所有这些文档。

(2)用户 文档的作用:充分有效的文档的优点如下:
1)改善易安装性
2)提高软件的易用性
3)改善软件的可靠性
4)促进销路
5)降低技术支持的费用
(3)用户文档测试需要注意的问题:
1)文档常常得不到足够的重视,文档的开发缺乏足够的资金和技术支持,而文档的测试更得不到重视。
2)编写文档的人可能并不是软件特性方面的专家,对软件功能可能了解得并不深入。
3)文档的印刷需要花费不少的时间,可能是几周,如果追求印刷质量的话可能需要几个月。
4)文档测试不仅仅是对文字的校对,更可以辅助找到更多的程序报错。
(4)用户文档测试的要点:文档测试中,对以下几个方面需要特别关注:

(5)针对用户手册的测试:
1)准确地按照手册的描述使用程序
2)尝试每一条建议
3)检查每一条陈述
4)查找容易误导用户的内容
(6)针对在线帮助的测试:
1)准确性
2)帮助是文档编写和程序编写的结合
3)帮助索引
4)超链接
5)链接的意义
6)帮助的风格
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)