跳到主要内容

5 篇博文 含有标签「DevOps」

查看所有标签

· 阅读需 10 分钟

悦库的目标客户是企业用户,是一款生产工具,对于工具制造商的我们第一要务是保证核心功能可靠性,其目的是提高客户生产效率。与之相对立的是:产品需要不断迭代和优化,用户的系统环境也在不断变化,这些变化都会影响到产品原有功能的可靠性。软件产品是由大量错综复杂的代码在不同平台运行的综合体,即使最专业的测试工程师甚至开发者自己也不能保证每次的修改不会产生不可预知的其他问题。

为了保证悦库产品健康可持续发展,我们自2022年在原有自动化打包流水线基础上,提出悦库持续交付系统概念,并一直在不断建设,到现在我们非常兴奋的宣布:

产品可靠性里程碑 => 实现全平台自动化测试覆盖,从悦库网盘5.6版开始,产品发布完全由持续交付系统接管,所有发布包都由测试流水线验证通过后才能发布。

持续交付系统

悦库持续交付系统是基于Jenkins建立的一种由4条流水线,7台虚拟主机/2台树莓派,以及各种脚本和测试用例组成的全平台软件交付系统。目的是:使用一种软件系统维护另外一种更复杂的软件系统的健康发展,摒除人类工作的高昂成本和不可靠特质。

持续交付系统的4条流水线,及其功能:

构建/测试/发布三条流水线的依赖关系如下,而活动流水线是定时自动循环触发的。

测试覆盖度

自动化测试的覆盖度是一个逐步建设过程,理论上代码和功能覆盖度越高越好,但受限于人工测试和机器测试的性价比,我们会更偏向于将机器性价比高的测试任务实现自动化,这类任务一般有以下特点:

  1. 产品入口功能,对新用户的体验很重要,出现问题会直接流失新用户,品牌形象恶劣。例如悦库的服务端/客户端全平台部署、升级功能。
  2. 产品的基础/核心业务,对用户很重要,出现问题会对用户造成重大影响,每次发布新版必须确保可靠的。例如悦库的文件存储/上传/下载功能。
  3. 有固定标准,不经常变动的API接口。
  4. 一些后台任务,人工测试不方便的或难以人工验证准确性的。例如悦库的后台数据清理和审计等功能。

单元测试是基于代码函数级别的测试,实施成本很高,适用于逻辑复杂且对准确性要求严苛的领域,如操作系统、航空航天、金融、区块链等领域。

目前悦库的测试流水线建设情况如下图:

image-20231024145734082

覆盖的测试范围包括:

  • 服务端(单机版/集群版)部署和升级测试,包括:Windows / Linux平台 。
  • 客户端部署和升级测试,包括:Windows、Mac、Web、Linux X64 deb package、Linux X64 rpm package、Linux ARM64 deb package、Linux ARM64 rpm package 。
  • 客户端上传/下载测试,包括:全平台客户端上传下载文件/文件夹测试。
  • Web端基本功能测试,包括:登录、创建空间、上传下载文件/文件夹测试。
  • API测试,正在持续建设中。

目前的测试流水线测试上述任务的运行时间为3小时左右(树莓派性能太差,导致ARM版部署测试很慢),过程中无需任何人为干预,节省大量人力成本同时持续的提高发布产品的速度和可靠性。为了进行全平台覆盖测试,测试流水线需要协调9台主机,在不同的操作系统和CPU架构的平台上进行测试验证,复杂程度可见一斑,并且维护流水线运行的稳定性本身也是有不少的工作量,所以自动化测试成果是显著的,背后的成本也是高昂的。

自动化测试实现

测试流水线中的每一个任务都是一组特定功能的测试用例,对不同的场景分别编写测试用例,然后使用Jenkins流水线脚本串联起来,就形成了测试流水线。

在测试脚本语言方面我们选择Python语言,它简洁优雅,生态丰富,易于学习。测试框架选择pytest,它同样简洁优雅,易于学习。

以下是测试流水线的部分脚本实例,可以看出在这个stage(阶段)中调用了linux_x64_centos9linux_arm64_centos7远程主机上的python 测试用例脚本:

      /*集群版服务端-安装/升级 */ 
stage('cluster server install/upgrade') {
parallel {
stage('linux_x64') {
steps {
bat "ssh linux_x64_centos9 sudo ~/ydisk/lib/systest/start.sh ./test_server_linux.py --cpu_arch x64 --cluster true"
}
}
stage('linux_arm64') {
steps {
bat "ssh linux_arm64_centos7 sudo ~/ydisk/lib/systest/start.sh ./test_server_linux.py --cpu_arch arm64 --cluster true"
}
}
}
}

对于无UI交互的逻辑业务测试,测试框架都会直接支持,但一些测试用例不得不与UI交互,例如客户端升级完成后需要自动登录,验证是否登录正常;Web端上传下载文件的测试则只能在浏览器中进行。这需要使用另一工具 Selenium ,进行网页自动化操作,由于悦库客户端基于Electron,因此也适用该工具。

最终,我们使用Python+pytest+Selenium 的技术栈实现了所有测试用例,其效果如下:

  • UI人机交互业务,Web端文件(夹)上传下载业务的自动化测试效果: Web_updown_test

  • 逻辑业务测试,Windows 服务端部署安装/升级自动化测试效果: image-20231024164115248

结束

九层之台,起于累土,当前的悦库持续交付系统仍处于累土阶段,尤其是测试流水线部分,需要继续建设。

产品质量的可持续发展,何其难也,为此,我们探索自内而外的改革,调研学习并尝试TDD(测试驱动开发)等一些成熟的软件开发理念,实现产品质量可持续发展的目标我们是认真的坚定不移的。

相关链接

持续稳定的交付产品

持续交付加速产品迭代V2

持续交付加速产品迭代V1

· 阅读需 8 分钟

目标:在每次版本发布时,保障产品的稳定可靠。

在软件开发中,从用户需求到交付可用的功能通常需要经过:需求分析、软件设计、需求拆分、任务拆分、编码、测试、验收交付等步骤。由于需求理解的偏差、设计的缺陷、编码错误等等原因,Bug会以各种形式出现在各个阶段出现。

我们如何能最大限度的降低Bug出现的频率和所带来的影响?

什么是TDD

TDD,英文全称Test Driven Development (测试驱动开发),是一套用于敏捷开发的方法论。简单来说,TDD是在编写业务代码之前,先实现测试用例,然后通过编写业务代码来满足测试用例的要求。

TDD的基本流程如下:

ATDD和UTDD都是TDD的实践。

ATDD,英文全称Acceptance Test Driven Development(验收测试驱动开发)

ATDD强调客户产品研发测试之间的相互配合,对需求进行沟通、分解和确认,让团队中所有人对需求的理解达成一致。由测试定义能够满足业务需求的验收标准。再由研发根据验收标准编写业务代码,并确保业务代码能满足验收标准。ATDD的目标是确保交付的功能满足客户的业务需求,与客户保持紧密的联系和协作。

UTDD,英文全称Unit Test Driven Development(单元测试驱动开发)

UTDD强调在编写业务代码之前先实现单元测试。在UTDD中,同样要求产品研发测试参加需求评审,要保证团队所有人对需求的理解达成一致,并对需求进行差分成更小的需求点,由测试根据需求点来编写单元测试,然后研发编写业务代码来实现这些测试要求。通过不断实现可通过单元测试的需求点,团队可以确保每个需求点的稳定可交付状态。UTDD的目标是通过单元测试来驱动业务需求的开发,提高了业务逻辑的稳定性。

ATDD适合满足客户的定制开发需求,保证交付的功能满足客户业务需求。UTDD适合在产品功能持续交付过程中,为业务逻辑的稳定运行提供可靠的保障。

如何使用TDD

在传统的“瀑布式”开发中,测试仅作为软件开发周期中的一个阶段。通常在需求研发阶段之后,交付之前,进行测试工作。一个用户故事转换为需求的过程,由产品经理参与和制定。之后需求交由项目经理,又被拆分成多个开发任务再分派给研发人员。研发人员接到开发任务后,开始编写业务逻辑;由于开发人员缺乏对需求的深刻理解,在业务逻辑的实现细节上存在诸多问题,在测试阶段往往会出现大量BUG,导致无法按时交付。

不同于“瀑布式”开发,在敏捷开发中,测试应该贯穿于整个迭代周期,从需求的理解到任务的拆分,从需求点的实现,再到最终交付,都需要有测试的参与,才能保证早发现早处理。

  • 我们面临的问题

    • 在需求分解阶段,团队没有参与验收用例的编写,只专注于需求点的拆分和研发任务的拆分。
    • 验收用例不够详细,只列出了粗略的验收标准。
    • 测试主要集中在研发结束之后,会出现由于对需求的理解不够透彻,导致推倒重做。
    • 测试过于粗糙,功能点覆盖不全面。
    • 开发新的功能时,影响了原来已经发布的功能,但测试时很难考虑到。
  • 如何解决

    • 团队中的所有人,参与到需求的评审和分解中,对需求理解达成一致。
    • 需求分解过程,用例先行,通过对用例的设计与实现,更深刻的理解需求并推敲需求的合理性。
    • 每个需求点完成后都要通过测试用例验证。
    • 测试用例要有可维护性,在新增业务时,增加对应的用例,调整业务的同时,更新原有用例。保证新老业务逻辑的稳定运行。
    • 在Jenkins流水线中集成测试,保证每次发布的版本都能通过自动化测试的验证,随着用例的覆盖率提高,产品的稳定性也随之提高。
    • 使用合适的测试方法:
      • 基于API的测试:根据API文档说明,通过HTTP协议,构建并向服务端发送HTTP请求,并对应答数据进行分析以验证接口的有效性。针对API的单元测试,粒度小,覆盖更全面,但实现成本也更高。
      • 基于UI的测试:使用测试框架,通过编码实现对UI的操作;通常基于验收用例,模拟业务使用场景,进行操作实现验收用例的测试。
      • 基于SDK的测试:基于SDK提供的接口,通过编码实现验收用例。

· 阅读需 6 分钟

悦库经历了过去一年快速功能迭代,文件管理业务逐渐丰富,为了确保在快速开发迭代的同时保证产品质量,今年5月份我们在现有持续交付流水线V1基础上进行升级,增加自动测试任务以帮助悦库实现稳定质量的可持续发展。

计划

自动化测试主要包括单元测试、API测试、UI测试、系统测试、性能测试等,每一种测试方法都针对不同工程维度,全面覆盖需要大量的人力,我们在资源有限的情况下,需要首先解决当前面临的优先级最高的测试问题,然后根据我们产品个性,制定一个中长期的实现愿景。

悦库每次发布前,必须要做的工作是安装和升级测试,要确保新用户首次安装和老用户升级后基础功能可以正常使用,但做这项测试工作需要在多平台下(Window、Linux X86/ARM64)人工完成,很费时费力,所有平台做一次测试需要至少2小时,且人工测试过程很难在各个平台中全面覆盖基础功能。

我们首先实现对多平台部署测试自动化,然后对服务端主要API进行自动测试覆盖,测试任务实现后立即加入持续交付流水线。

迈出第一步

我们选择使用基于Python的pytest测试框架,简单易上手,辅助Copilot AI结对编程,提升了不少工作效率。

自动化部署测试分为首次安装测试和升级测试,需要分别对Windows、Linux X64和Linux ARM64三个平台进行测试,基本流程如下:

首次安装测试:

  1. 保存当前测试机原有环境。

  2. 获取流水线构建好的安装包,命令行运行执行安装过程。

  3. 登录测试,验证服务安装有效性。

  4. 使用yshell(悦库命令行客户端)执行新建、上传/下载、删除等基础用例,确保基础功能有效性。

  5. 还原测试机环境。

升级测试和首次安装测试差别在于需要先使用yshell从悦库内盘存档中下载当前平台上一次发布包,部署安装并执行升级后验证基础功能有效。

以下是构建流水线中的安装/升级测试任务:

image-20230530161256951

如果测试任务失败是这样的:

image-20230530163326409

直接点击出错任务节点,查看原因:

image-20230530163514939

下一步

我们现在已经实现了基本的安装/升级测试,这也仅仅是实现悦库单服务器版本。下一步我们将实现集群版的部署和多平台客户端自动部署测试,在发布流水线中增加对官网在线体验Demo和内盘的自动发布升级。

远方

凡事皆有利弊,自动化测试提高了测试效率的同时,也增加了测试用例实现和维护成本,一旦测试目标发生业务变更对应的测试用例也需要调整,因此从成本上考虑,应该选择对业务较为稳定成熟的工程模块进行自动测试的用例覆盖,理想主义思维容易陷入焦油坑。

悦库现在致力于对部署和核心API进行用例覆盖,其中API用例覆盖将是一个长期持续的过程,需要对工程人员进行培训,以适应开发API同时为其添加测试用例的工作方式。

另外,测试用例任务是必须与持续交付系统集成才有意义,这样每日构建时可以尽早发现问题,尽早解决~

· 阅读需 6 分钟

本文指导用户使用悦库网盘的yshell命令行客户端,实现对DevOps产物(测试包和发布包)自动归档到悦库网盘中。前提是需要安装并使用悦库服务端。

悦库团队的DevOps实践

悦库网盘产品团队内部DevOps实践中,不断完善产品交付流程自动化,结合使用敏捷式开发,实现了持续快速交付产品。目前每次版本发布时间稳定在2~3周之间。

以下是悦库基于Jenkins的全平台持续交付流水线在2022年4月8日的每日构建运行状态:

image-20220409222701194

发布是单独的流水线,持续交付流水线完成后,可由人工触发,目前只有一个脚本文件,比较简单:

image-20220410130644777

我们认为做好Devops实践是实现敏捷交付的重要前提,尽可能解放团队成员重复劳动,减少不需要的麻烦,尽早发现交付风险。

悦库内盘是悦库团队使用自己的产品搭建的内部文件管理系统,用于团队中的文件管理。

在每日构建和自动发布完成后,使用yshell的命令行自动归档到我们的悦库内盘中,方便大家随时下载测试包和各个版本的发布包。

用yshell实现自动归档

由于悦库流水线的主构建机为Windows Server系统,因此下面示例是在Windows系统上运行的,yshell命令在Windows/Mac/Linux系统上执行效果完全一致。

  1. 配置yshell命令

    参考官方文档

  2. 在悦库网盘中添加一个归档账号

    例如:用户名为 jenkens , 密码 666666 。并设置对归档目标路径 "/公共空间/悦库安装包" 有完全控制权限。

  3. 对测试包/发布包进行归档

    以悦库流水线为例,执行完成后最终会生成5个不同版本的服务端安装包:

    image-20220410122024998

    以下归档脚本 ydiskArchive.bat 功能实现,用户可根据自己环境的实际情况自行修改:

    由于目前yshell不支持上传目录下所有文件功能,因此需要逐个上传,我们后续会逐渐增强功能!

    @echo off
    rem 脚本功能描述
    rem 参数为归档类型:test(测试包)或release(发布包),使用举例:ydiskArchive.bat test
    rem 每日构建执行完成后,将所有生成的测试安装包上传到悦库内盘公共空间的"sprint"目录中。
    rem 自动发布执行完成后,将所有发布包上传到悦库内盘公共空间的"release"目录中。
    rem ysh执行失败会返回非0值,应该从将这个值从脚本中返回,这样Jenkins可以识别错误并中断构建任务。

    rem 切换到当前脚本所在目录
    cd "%~dps0"
    %~d0

    rem 归档方式为test或release
    set ArchiveType=%1

    if "%ArchiveType%"=="" (
    echo "请输入归档类型参数,test或release !".
    exit /b 1
    )
    echo Archive type is %ArchiveType%

    rem 获取当前版本号
    set /p CurrVersion=<../version.txt
    rem 获取当前git分支
    set CurrBranch=""
    for /F %%i in ('git rev-parse --abbrev-ref HEAD') do (set CurrBranch=%%i)
    echo version is %CurrVersion% , git branch is %CurrBranch%

    rem 构建悦库网盘目标路径
    set YDiskPath=""
    if "%ArchiveType%"=="test" (
    set YDiskPath="/公共空间/悦库安装包/sprint/%CurrBranch%"
    )
    if "%ArchiveType%"=="release" (
    set YDiskPath="/公共空间/悦库安装包/release/%CurrVersion%"
    )
    echo YDiskPath is %YDiskPath%

    rem 配置悦库登录地址、用户名称和密码
    ysh user -u http://192.168.0.102:2020 -a jenkens -p 666666
    if not %errorlevel% == 0 (exit /b %errorlevel%)

    rem 在悦库中以分支名称创建文件夹。使用-p参数,如果空间或文件夹不存在会自动级联创建。
    ysh mkdir -p %YDiskPath%

    rem 上传所有安装包,如果包已经存在则会覆盖。要获取历史包可以在该文件的历史版本信息中下载。
    ysh put -f "../output/ydisks_win64_free.exe" %YDiskPath%
    if not %errorlevel% == 0 (exit /b %errorlevel%)
    ysh put -f "../output/ydisks_docker_x64.tar.gz" %YDiskPath%
    if not %errorlevel% == 0 (exit /b %errorlevel%)
    ysh put -f "../output/ydisks_docker_arm64.tar.gz" %YDiskPath%
    if not %errorlevel% == 0 (exit /b %errorlevel%)
    ysh put -f "../output/ydisks_cluster_docker_x64.tar.gz" %YDiskPath%
    if not %errorlevel% == 0 (exit /b %errorlevel%)
    ysh put -f "../output/ydisks_cluster_docker_arm64.tar.gz" %YDiskPath%
    if not %errorlevel% == 0 (exit /b %errorlevel%)
    exit /b 0
  4. 将脚本加入到Jenkins流水线中

    在流水线中的归档任务:

    image-20220411212124790

    归档到悦库内盘后的 "sprint34"期 的测试包:

    img

· 阅读需 7 分钟

悦库网盘最早期仅支持window平台部署,现在服务端和客户端都支持多平台,随着支持的功能越来越多,系统的复杂度也大幅增加,每次迭代时间越来越长,导致迭代经常延期,产品交付后问题频发。

面临的问题1: 需求实现后不能立即测试验收

在敏捷开发模式中,产品需求在迭代中开发完成后需要尽早进入测试阶段,而不是等到所有需求都完成才进行测试,这样可以让问题更早被发现和处理,降低集成测试的BUG数量,从而降低迭代延期风险。

在悦库网盘产品的前期迭代过程中,我们就遇到很多问题,举例:

在需求开发阶段,通常是开发人员各自实施自己的任务,将完成任务并提交代码后认为需求开发完毕。但此时做完的需求由于没有集成和打包,通常处于一种测试人员不可用状态,测试人员只能等待开发人员打包后才能进行测试。

在需求测试阶段,如果发现BUG,开发人员修改后需要重新打包测试人员才能验收。

每次版本发布前问题都特别多,需要不断的 “测试->修复->打包->验收”,对于复杂的多平台兼容系统,打包和部署的时间成本是非常高的,阻碍了整个团队工作进度。

面临的问题2: 产品集成复杂

每一个复杂的软件产品从程序员写完代码到安装包部署到用户生产环境都是一个复杂的过程,仅以悦库网盘windows客户端的构建流程为例:

  1. 编译32位虚拟盘服务。
  2. 编译64位虚拟盘服务。
  3. 编译3个32位explorer扩展dll
  4. 编译3个64位explorer扩展dll
  5. 构建electron资源文件。
  6. 执行打包脚本:包括注册explorer扩展dll、检查并下载安装系统补丁、安装虚拟盘驱动、修复和升级处理等。
  7. 对安装包签名。

在前期只有windows客户端时,我们通过编写一个批处理文件进行自动打包可以很好的解决问题,随着产品技术栈的复杂度和平台数量的增加打包的复杂度呈指数级增长,目前我们需要分别在windows、linux x64、linux arm64、mac 四个平台上构建客户端和服务端,并将四个平台客户端分别集成到不同平台的服务端中,再考虑后续的手机端,这样的集成复杂度是靠人工是难以实现且非常低效的。

面临的问题3: 产品发布费事费力

产品发布时,需要做的工作:

  1. 将多个平台的发布包上传到官网

  2. 发布新版用户手册和开发手册到官网

  3. 在CDN中刷新URL,使下载链接立即生效

  4. 归档所有发布包到服务器

  5. 更新官网下载页面的版本号和发布时间

这些工作重复且无聊~

我们理想中的它是什么样子?

能够在主服务器中对多个目标平台构建发布包,构建完成后自动部署测试环境。

支持多分支,定时检查代码提交行为,如有提交则触发自动打包和部署。

一键发布所有平台安装包并完成归档。

它的存在,是为了让团队能将时间和精力更专注于产品业务实现。

创造它~

通过技术调研,最后我们决定使用Jenkins搭建持续集成环境。

主服务器是一台window service主机,安装了Jenkins,同时可以在其上构建windows平台的客户端和服务端安装包以及部署测试服务端。其他4台主机是平台构建机,实现在非windows平台下构建和部署客户端及服务端,最终构建的所有平台服务端安装包由主服务器收集并完成发布。

持续集成系统主机组成结构?下:

image-20211229232605934

构建过程:

image-20211230095003837

构建过程包括对升级版本号、OEM定制、构建docker镜像、打包、签名、部署等任务。

每一个任务都有对应的任务日志记录,便于失败后排查问题:

image-20211230152709410

它并不完美,但它一直在完美中...

持续交付VS持续集成

持续集成是将产品的各个组件构建并集成,达到一种可部署和可测试的状态。

持续交付是在基于持续集成的工作基础上让集成后的产品可以会直接交付给客户使用,这需要针对主要功能增加自动化测试用例,跑通自动化测试用例的组件或产品认为是可交付状态。

持续交付能力是悦库网盘产品的重要目标愿景之一,我们将为此持续努力。

“我的存在是为了让你们更好的专注于产品业务!”