在一个项目的生命周期 (SDLC)内,代码被团队开发、编译、构建以及部署到不同的环境。 常见的环境/服务器如DEV、SIT、UAT、PRE、PROD等。
这些不同的环境/服务器各自具有怎样的定义,以及各自承担什么样的分工呢?
本文将对上述项目环境进行简单介绍。
1. Background: SDLC and DevOps
使用多个环境可以确保软件在部署和交付给真实用户(客户)之前经过严格的测试与控制。
1.1. SDLC (Software Development Life Cycle, 软件生命周期)
软件生命周期
是指软件从生产到报废的全部过程
。 它是软件工程中的一种思想原则; 即按部就班、逐步推进
,每个阶段都有其定义、工作、审查、形成文档以供交流或备查,目的是在尽可能短的时间内,生产出最高质量和最低成本的软件。
早期的软件生命周期处于无序、混乱的样子。一些人为了能够控制软件的开发过程,就把软件开发严格的区分为多个不同的阶段,并在各个阶段间加上严格的审查。
在软件开发的过程中,开发团队将会遵循SDLC的流程: 每一个团队成员执行的任一步骤,都是SDLC流程的一个步骤。 这些流程能够帮助团队确保被开发的项目从开始到结束均有一个清晰的路径。
软件生命周期通常可以分为以下几个阶段:
1. Requirement Analysis (计划与需求分析) and Planning (计划)
软件开发生命周期从分析开始,过程的利益相关者讨论对最终产品的要求。此阶段的目标是对即将开发的系统/软件的要求的详细定义。
此外,还需要确保所有流程参与者都清楚地了解任务以及每个需求将如何实施。2. Design of Archiecture (项目架构的设计)
在软件开发生命周期的第二阶段,开发人员开始设计架构。
有利益相关者(包括客户)都会讨论此阶段可能出现的所有不同技术问题。
此外,这个过程还将定义了项目中使用的技术,团队负载,限制,时间范围和预算。
最合适的项目决策是根据上一个环节(Requirement Analysis and Planning) 定义的要求做出的。3. Development (开发和代码)
在批准要求后,该过程进入下一阶段 - 实际开发, 团队成员根据各自的分工职责开始工作。
程序员们将从这个步骤开始编写项目的源代码(通常包括算法开发、源代码编写、汇编、测试与调试),同时牢记先前定义的需求;系统管理员则调整软件环境;前端程序员开发程序的用户界面以及与服务器交互的逻辑。4. Testing (测试)
开发过程中遗漏的所有代码缺陷都会在此处检测到,记录下来并传回给开发人员进行修复。
重复测试过程,直到删除所有关键问题并且软件工作流程稳定。5. Deployment (部署/上线)
部署,即:将代码发布到各种环境。
如:Test环境以供测试验收, PROD环境交付给客户使用, 等等。
而在上述步骤中通常涉及相应阶段工作所在的服务器或环境。在软件开发过程中的每一步,都决定了代码将在各个服务器/环境间如何移动,直到最终完成开发及上线。
1.2. DevOps and CI/CD
在当今的商业环境中,实施DevOps也逐渐成为维护大型项目以及参与多个项目开发的重要要求。DevOps提供了很多工作流程与工具,使团队工作更加有效与高效。
无论我们采用哪一种DevOps工作流程以及使用哪些DevOps工具;对于任何一项重要的开发项目,使用多个环境
已成为广为推荐的做法。
随着DevOps思想的兴起与发展, 软件开发的的方法中也出现了CI (Continuous Integration)/CD (Continuous Delivery & Continuous Deployment)等新的思想:
CI/CD是实现敏捷(Agile)和DevOps理念的一种开发方法。 具体而言,CI/CD 在一个应用的整个生命周期中实现了高度持续自动化和持续监控; 而关联的事务通常被统称为”CI/CD Pipeline”,由开发、测试、运维团队以敏捷方式协同支持。
而在这个过程中,开发/测试/预发布/生产: 不同的角色工作在不同的环境中,不同的环境也有不同的作用。 因此, 对软件环境的合理设计与分配显得更加重要。
2. 项目开发流程中的环境部署对项目执行/管理的帮助
2.1. 不同场景 (开发、测试以及真实业务)的隔离与对接
软件的开发、测试与真生产环境区分的主要原因是: 避免开发、测试与真实产品工作之间的相互混淆与干扰。
开发的过程中涉及大量的测试与调试。而一个不正确的程序/功能很可能会破坏服务器的内存、CPU内核、磁盘I/O并将其“挂起”。
想象一个软件服务的开发、QA、压力测试、用户交付等工作全部只在一个环境中进行; 如在程序开发/更新、测试的过程中,有些不正确的程序逻辑或操作导致了应用的崩溃,必将对实时用户及关健业务数据造成严重影响。 而系统修复/调试期间,相应的其他职能(如QA/压力测试甚至其他模块的开发/调试与部署等)也必将瘫痪,真实业务也将随之陷入停顿。
2.2. 服务器环境/资源/数据/权限/日志级别的合理设置及分配
如一台服务器同时用于开发、测试和生产,则意味着上述工作需要共享服务器的资源(共享数据库、磁盘I/O、CPU、网络带宽等),服务器将承载来自各项操作的压力;最终影响生产环境(即真实业务环境)的性能。
而开发、测试与生产环境的应用,对服务器的性能需求可能并不相同。细分为多个环境,团队可以根据不同环境的实际需求,为环境分配合适的系统资源,让各个环境能够更好的工作,以及互不占用各自的资源。
相应的,因为产品真实环境的数据通常不便用于直接展示和调试/改写,不同环境的隔离也能够有效保护业务数据;开发/测试人员可以在初期环境中被授权访问和改写测试数据而在生产环境不被授权访问和改写相同的范围。
相应的,为了支持不同的环境所需的配置:在项目配置信息维护的层面,项目开发/运维人员可以将针对不同环境配置的文件分别设置成:appsettings.json
, appsettings.staging.json
, appsettings.QA.json
, appsettings.Development.json
等多个文件; 在各自的配置文件中,设置不同的配置项的属性值; 从而能够在不同环境部署和更新应用的时候,迅速配置当前环境适配的属性。
常见的不同环境配置项:
- 数据库Connection (包含DB-connection的ip/username/user-grant读写权限/等);
- 外接/挂载存储或缓存的路径;
- 第三方调用及依赖的API/URL/路径/Token等;
- 应用对外的端口(PORT);
- 区分各个环境的标准信息;
- 当前环境为应用分配的环境资源/参数/备份策略等.
3. 项目开发流程环境部署的需求: DTAP
DTAP,即: Development
, Testing
, Acceptance
and Production
; 翻译成中文的意思,即:”开发、测试、验收和生产”。
在WIKIPEDIA中有一个相对官方的定义: https://en.wikipedia.org/wiki/Development,_testing,_acceptance_and_production ; 描述了一种分阶段的软件测试和部署的方法:
Development: 开发人员在一个专门的开发系统或环境上开发一套程序或一个组件;这个环境可能有,也可能并没有设置测试功能。
Testing: 当开发人员认为对当前程序或组件的开发工作完成时, 当前的程序或组件将被复制到用于测试的系统或环境中, 以支持测试人员对相应的功能进行验证。
Acceptance: 有时也被称为”Staging”。 如上一步测试成功, 程序或组件将被进一步复制到验收环境。 在验收测试(Acceptance Test)期间,这套程序或组件的真正的客户将在此环境中测试和验证产品是否符合他们的预期。
PROD: 如在验收测试期间, 客户接受了这套程序或组件,它将进一步被部署在生产环境(PROD)中。此时它将成为一个真正的对外服务的产品, 供所有的真实用户使用。
而用于DTAP流程的环境集合通常被称作: DTAP-Street
.
4. 常见的项目开发流程环境举例
环境配置管理主要是针对应用对基础设施和基础服务依赖关系的配置管理。 具体如何设计多个开发流程环境以及各环境的职能,还是要根据这个应用自身的交付流程来设计。
对于体量较小的应用来说,最简单的环境分配方式是仅设置DEV
和PROD
两个环境; 而对于大部分普通体量的应用来说,通常会设置DEV
/TEST
和PROD
三个环境; 对于体量相对复杂、生命周期中需要较多的团队协同的应用来说,则会需要设置更多不同分工的环境。
根据之前提到的DTAP流程,我们可以选择如下几种常被涉及的环境进行了解:
4.1. DEV: Development (开发环境)
用于开发周期内,开发人员对自己(团队)实现的代码进行访问/联调与基本功能验证。
DEV环境服务器的配置相对较低,不会考虑太多负载/压力/缓存等性能因素。
关键字:
Debug
,Joint Debug
,Unit Test
,Compile
,Build
,Quality Metric
,Code Inspection
,Programmer
,Internal Validate
,Ready for Test
常用工具:
SonarQube
,JUnit / TestNG / pyTest
,Maven / Gradle
,Docker
,Postman / Apache JMeter / Swagger
4.2. SIT: System Integrate Test (系统集成测试环境)
SIT环境用于开发周期结束后,验证开发周期内各个开发模块的交付成品集成效果的测试(非功能测试)。在这个阶段,集成测试的主要目的是校验功能、性能和可靠性要求。
负责SIT测试执行的群体通常是技术项目测试人员 (QA);少数情况下也可有开发者的介入。
测试人员根据用例描述测试/模拟每一个功能使用场景; 如在测试过程中发现错误或其他问题,QA测试团队将会为开发团队创建任务或defect进行修复。
在DEV和SIT环境,应用的日志级别通常会设置较低(ALL/DEBUG/INFO或WARN), 便于调试和验了解状态。
软件在SIT环境的配置通常与DEV环境基本相同,也没有研发团队外部的人员进入。
SIT的主要功能是测试系统各个部件之间的依赖关系,因此回归测试 (Regression Testing)是SIT的重要组成部分。 在一个Sprint中的最小可行产品(MVP: Minimum Viable Product) 也只有在SIT测试通过后才会发布。
SIT可交付的成果则传递给UAT(用户验收测试)。
系统集成(SIT)测试通常有两种方法:
1. 自顶向下集成方法 (Top-Down Integration Approach):
模块通过在层次结构中向下移动来集成。从顶层控制模块(主模块)开始,对各个模块一边组装一边测试。这种测试方法的思路同系统模块的设计顺序是一样的。
在自上而下方法中,如果较“下”的模块没有准备好,则使用一个叫做“存根”或“桩模块” (Stub)的虚拟模块替代它进行测试。 Stub模块具有测试“上一个”模块时所需的最基本的功能。
2. 自下而上集成方法 (Bottom-Up Integrtaion Approach):
在这个方法中,测试将从依赖性最小的底层模块开始,逐层向上集成。
如果“上层”模块未准备好,则使用驱动程序(Driver)进行测试。 驱动程序是一个专门用于测试的程序。
关键字:
Internal Testing
,Use Cases
,Integartion Test
,Cross-Module
,QA Engineer
,Functionality
,Stability
,Bug/Defect Feedback
,Ready for Approval
常用工具:
JIRA
,Selenium
,Apache JMeter
,Zehpyr
4.3. * QAT: Quality Assurance Test (质量保证环境)
虽然听起来和UAT有点相似,但两者不一样。QA测试更加专注于产品自身的质量。
QA测试用于确保产品在交付到UAT环境/流程之前避免错误和缺陷。
而QAT与UAT的取舍、选择或组合也因团队实际需求而异,也取决于项目管理的方法: 在瀑布模型中, QAT通常在UAT之前;而在敏捷开发模型中,QAT和UAT则是相互依赖,不一定要按照先后顺序来完成。
如果项目没有设置UAT环境,则UAT测试通常会安排在QAT环境执行。
4.4. UAT: User Acceptance Test (用户验收测试环境)
可以被理解为功能测试,主要被用作产品的真实用户的体验环境。
当程序通过内部测试阶段并准备好接受审批时,团队将会把程序部署到UAT环境。
UAT测试由专门的UAT团队或真实产品用户完成;侧重于业务,所以UAT测试人员通常对业务更精通而不需要关注程序的底层逻辑。 用户根据用例描述测试每一个场景,反馈系统issue。开发人员基于issue对系统影响和对业务impact判断,适当的修正系统或记录业务需求,根据业务优先等级,集成进下一个演进阶段。
UAT环境所在的服务器配置/依赖和性能应该与PROD环境(生产版本)基本相同, 但可以暂不考虑缓存/高负载等复杂性能问题。
此时开发人员或其他技术人员在UAT环境将不再有权限,只有功能测试人员才被授权访问。
程序到了UAT环境, 通常日志级别会调整至WARN或ERROR。 同时,环境的配置及测试的标准也将兼顾程序的性能(如压力测试)。
UAT测试通常又包含Alpha测试
和Beta测试
两种类型:
- Alpha测试通常在系统测试(System Testing)完成后执行。这种测试通常是在开发人员的控制执行的 客户在开发人员的站点进行测试。
- Beta测试仅在Alpha测试完成后执行, 不再受开发人员控制, 由软件的最终用户在一个或多个客户站点进行。 Beta测试权限将会提受信任的用户。
关键字:
Internal Testing
,Client / End-Users / Business Users
,Registered Tester
,User Experience
,Overall Functionalilty
,UAT Approve / UAT Sign-Off
常用工具:
TestFlight / PlayStore / Watir / Fitness Tool
4.5. LT: LoadTesting (负载测试环境)
负载测试是一种非功能性软件测试过程, 它反映了被测试的软件在同时被大量并发虚拟用户在特定时段内访问/执行事务时的性能。 简单来说,即”衡量系统处理大量负载时的性能”。
负载测试的目标是改善软件的性能瓶颈,提供消除这些性能瓶颈所需的诊断信息。 能够让软件在部署到PROD环境前,确保各个组件自身的稳定性和流畅性,符合指定的性能标准。 (因此,与UAT 环境相似, LT环境所在的服务器配置/依赖和性能也与PROD环境基本相同。)
测试人员在负载测试环境中配置测试来模拟各种用户场景,这些场景可以专注于系统的不同模块(如: 订单结算, 历史记录查询等)。 在负载测试环境,测试人员可以确定负载在来自不同的地理位置时的行为方式,或负载如何累积随后保持稳定。
负载测试通常被建议集成到持续集成(CI)周期中,以确保软件能够始终处于正确的状态。这就是我们为什么需要设置负载测试环境。
负载测试是性能测试(Performance Testing)的一种。 而性能测试是负载测试和压力测试(Stress Testing)的总称。 相应的, 大型的项目也会根据实际需求,设置压力测试环境或性能测试环境,用以支持相应类别的性能测试。
关键字:
性能测试
,Vuser Script
,并发
,模拟
,QA
常用工具:
LoadRunner / Apache JMeter / Loader.io / [Fortio](https://github.com/fortio/fortio)
4.6. * Staging / PRE-Deployment (临时环境 / 预发布环境)
类似于“彩排”; 是产品进入生产环境(PROD)前的最后一步。
预发布环境所有的环境配置参数、架构和代码版本完全相同, 在这里,开发团队进行冒烟测试。
当所有的团队成员, 包括UI/ 后端开发人员、Devops、DBA等对产品进行检查,且确认产品功能/内容无误, 产品将会被推向生产环境(PROD)。
关键字:
Smoke Test
4.7. * Demo (演示环境)
演示环境不像其他环境那样常见;通常是基于客户的特殊需求才为一个产品设置一个演示服务器。
演示环境本质上可以理解为生产环境(PROD)的冻结版本。设置Demo环境的目的主要是为客户或利益相关者/潜在用户提供一个产品的样例。
一般在产品营销/市场团队会使用这个环境较多。
当产品完成开发且通过客户批准时,产品即可被部署在Demo环境(与PROD同步)。
关键字:
Sample
4.8. PROD/PRD/PRO: Production (生产环境)
PROD环境是应用程序正式对外的服务环境; 即程序或一次update的Release版本。
PROD环境通常在收到UAT认证(UAT Sign-Off
)并通过适当的变更管理流程之后,由专门的实施者在这里部署相关的版本; 并由官方渠道(如项目官网, AppStore等)公开提供给真实的使用者。
在这个环境,真实的用户将会使用最新Release的功能, 并将他们的问题/使用环境通过反馈渠道反馈给产品运维团队。
PROD环境一般会关掉错误报告,打开错误日志 (日志级别: ERROR);在这个环境,相关的权限仅被分配给真实的产品使用人员,开发/测试工作人员将不再有权访问PROD环境的应用。
关键字:
Released / Version
,Final Location
,Go Live
,Widespread Use
,Public User
常用工具:
Firebase Crashlytics
4.9. COB: Continuity of Business for disaster recovery (业务连续性环境/灾难恢复环境)
COB环境也通常被称为”COB测试环境”; 可以被理解为”PROD环境的备用环境”。当PROD服务器发生了故障或出现一些自然灾害而无法正常工作时,COB环境将迅速接替PROD进行响应与服务, 保持服务的正常运转。
COB环境所部属的应用及数据版本、用户权限、访问权限通常也与PROD(生产)环境保持同步。
关键字:
Back-Up
5. 项目环境的验收与推进: Test Sign-Off
Test Sign-Off是指软件在一个类型的测试(SIT / ST / QA / UAT 等)流程中,以正式形式 (通常为邮件或会议,即
Sign-Off Mail
或Sign-Off Meeting
)说明软件已通过测试用例(无重大缺陷),标记此测试环节已正确完成。 所有在这个阶段必要的测试方法和用例均已执行通过,可以准确交付到下一个测试或生产环境。当测试团队提供了相应测试阶段的Sign-Off,表示软件已正确通过这个测试的全部流程,可以交付到下一个环节/环境。
5.1. DEV → SIT: 单元测试 (Unit Test)
项目推进到SIT环境/阶段有一个先决条件: 多个底层集成模块已经经历且通过单元测试(Unit Test); 且在每次向系统中添加新的模块时进行SIT测试。
SIT随后会将当前交付的软件版本作为一个整体来测试这些模块之间所需的交互。
关于系统测试:
系统测试 (System Testing) 并不是系统集成测试 (System Integration Test)。 集成测试 (Integration Test)是较低级别的测试,更专注于系统各个模块之间的衔接和交互; 而系统测试是较高级别的测试,属于验收测试类别。系统测试将通过集成测试的软件与系统中其他部分(硬件、外设、网格、其他应用、支持平台以及操作人员)结合起来,验证最终软件系统是否满足用户规定的需求,更侧重于模拟现实的真实使用场景。
系统测试通常在最终级别进行: 即在完成集成测试后,交付UAT环境之前 (V模型)。
系统测试主要包括功能测试和健壮性测试(如恢复测试,安全测试和压力测试); 系统测试仅包含功能性测试,使用黑盒测试技术针对被测模块的接口规格说明进行测试。
有时候,SIT也会被理解为集成测试和系统测试的结合。 在这种情况下, 开发人员与测试人员们通常会执直接在SIT环境完成集成测试和系统测试。
5.2. SIT/ST → UAT: 系统测试 + SIT Sign-Off
SIT测试是一个迭代的过程。 当SIT/QA测试人员在发现新增代码的问题,以及原有代码被新增代码影响而产生的缺陷的情况,则会反馈给开发人员 (JIRA Issue / QA Issue) 进行修复和再次发布以支持SIT测试的继续进行。
UAT测试通常会在SIT (ST/QA)测试的下一个环节。
在软件进入UAT测试环节之前, 通常需要确保软件已经得到了SIT/QA Sign-Off。
5.3. UAT → PROD (and COB): UAT Sign-Off
UAT测试通常是软件产品检验的最后一个环节。
按照项目任务书或合同、供需双方约定的验收依据文档进行的对整个系统的测试与评审,决定是否接收或拒收系统。 如通过验收,系统将会被推进到生产环境。
在UAT测试期间,如发现软件存在任何缺陷(Defects)与错误(Errors),开发人员们会尽快修复和更新软件,提交给UAT测试人员再次检查。
当UAT测试已执行完成,并且在UAT测试期间的发现关键的Defects
/Bugs
/Issues
已被修复(Resolved
),这时UAT测试人员即可向相关人员发送一份邮件或报告,或发起一次会议等正式的形式告知软件已被签准(UAT Sign-Off
)。
当软件被标记为UAT Sign-Off,表明软件在UAT环境的状态/变更满足业务需求,并已准备好推进到下一个环境 (通常为PROD 生产环境)。
COB 环境的资源配置及软件版本通常要与PROD环境保持严格一致。因此,当软件被标记UAT Sign-Off后, 通常会同时推进到PROD和COB环境。
5.4. * UAT v.s. Load Testing (负载测试)
负载测试通常在项目开发接近尾声才开始。
从技术上讲, 负载测试也并不一定要等软件完全开发完成时才开始测试。 项目团队可以在任何开发过程的任何阶段以集中的方式测试指定的组件。
不过,如果是为了模拟测试数十万计的用户访问,最好的解决方案仍然是等待项目开发接近完成时执行。
所以在大部分项目生命周期中,项目move到LT环境/环节的时间接近于项目进入UAT环境/环节的时间 (或略微迟于项目推进到UAT环境/阶段), 在推进到PROD环境之前。
6. 参考文献及扩展资料
- User Acceptance Testing [UAT] Process Explained: https://www.panaya.com/blog/testing/what-is-uat-testing/