用爱发电!送你无价礼物!初创团队福音,端到端自动化测试的容器化持续集成解决方案。

背景

前端页面设计逐渐稳定,基于用户契约的业务流程逐渐明晰固化,每轮迭代不断重复的端到端测试,成了重要却枯燥的机械性点鼠标。此时测试团队需要打一剂强心剂,变化一些挑战,同时又不能太影响本职任务。学习成本的控制对管理者来说,也是一个挑战。

目标

  • 解放鼠标手,机器能替代的事情,绝不让人干。
  • 不擅长写代码的人也能参与其中。
  • 中文成为大家协作的官方语言。
  • 输出简洁可读、界面美观的测试报告。
  • 支持持续集成环境。
  • 支持在容器中运行。

工具选型

综合团队的武力值与成长,支持关键字驱动的自动化框架 RobotFramework 成为我的首选;考虑到团队的整体英文能力不足,有意设计中文关键字来驱动测试用例的执行,以避免日后工作中出现的各种理解上的幺蛾子;灵活轻量的多语言测试报告工具 Allure 框架,以简洁的 web 报表形式展示测试内容,其美观大方专业彻底征服了我;团队使用的 Jenkins 采用容器化部署,在整个设计中,测试任务流水线也将在独立的容器中运行,跑完即删,去污不留痕。更多考虑的细节不再一一赘述,以下是选好的框架集:

  • Chrome + Webdriver
    Webdriver 列表
  • Bash
  • Python3 和 依赖包
    requests pyyaml selenium robotframework allure-robotframework
  • RobotFramework
  • JRE + Allure Commandline
    Allure 安装方法
  • Docker
  • Jenkins 及插件
    docker allure

落地

直接分享

  • 可以点击下图访问 GitHub

图片

  • 若网速堪忧,也可以点击下图访问 Gitee

vstone/srfFramework

目录结构说明

图片

目录 作用 文件命名 文件内容示例
testcase 用于存放测试用例 <suite>.robot testcase/demo.robot
keywords 用于存放关键字
以便在编写 testcase 中的用例时引用
<menu><Page>.robot keywords/qsphereVision.robot
pages 用于存放封装好的页面元素操作函数
以便在封装 keywords 中的关键字时使用
<menu>/<Page>.py pages/qsphere/Vision.py
elements 用于存放页面元素的 xpath
以便被 pages 中的函数加载
<menu>/<Page>.yaml elements/qsphere/Vision.yaml
common 用于存放与产品解耦的基础函数
以便被 pages 中的函数调用
xxx.py common/Browser.py
config 用于存放用例执行过程中使用的全局变量和测试数据
以便在 testcase 或 keywords 中可以直接引用
xxx.yaml config/template.yaml
  • 关键字的封装是照顾到代码能力较弱的人,并且起到汉化的作用
  • 页面操作上的功能实现,是放在 pages 里的
  • menu 主要是对应一级菜单,page 主要对应二级菜单,能够定位到页,视情况而定

快速开始

准备配置文件
  • 复制模板
cp config/template.yaml config/demo.yaml
  • 修改 demo.yaml 配置中的变量值
# RobotFramework Configuration
# If you wanna debug via browser, you can set RF_DEBUG as true
RF_DEBUG: false

# Target Configuration
TARGET_URL: https://qualitysphere.gitee.io
TARGET_USER: will
TARGET_PASSWORD: password
TARGET_TITLE: 欢迎使用 | QSphere
执行测试用例
  • –config 指定配置文件执行测试用例
./sraf-cmd --config config/demo.yaml --clean
  • –tag 执行指定标签的测试用例
./sraf-cmd --config config/demo.yaml --tag demo --clean
  • –suite 执行指定测试集中的测试用例
./sraf-cmd --config config/demo.yaml --suite testcase/demo.robot --clean

更多用法请运行 ./sraf-cmd 查看

在本地容器中执行
docker build --pull -t sraf-cmd:local .
docker run --shm-size=1g --rm -p 80:80 -it sraf-cmd:local bash -c "./sraf-cmd --config config/demo.yaml --tag demo --clean --report local-allure"
# 若在 windows 中执行,需要在命令前面使用 winpty
winpty docker run --shm-size=1g --rm -p 80:80 -it sraf-cmd:local bash -c "./sraf-cmd --config config/demo.yaml --tag demo --clean --report local-allure"
在 testcase 目录中编写测试用例

testcase/test_case.robot

*** Settings ***
Documentation       用例集描述
Resource            ../keywords/<menu><Page>.robot     # 引入关键字资源
Test Setup          SRAF.开始测试
Test Teardown       SRAF.结束测试

*** Variables ***

*** Test Cases ***
SRAF 测试用例标题
    [Documentation]     用例描述
    [Tags]              标签1    标签2
    SRAF.menu1.Page1.关键字1
    SRAF.menu1.Page1.关键字2

*** Keywords ***

在 keywords 目录中封装关键字

keywords/<menu><Page>.robot

*** Settings ***
Documentation    关键字说明
Library    ../pages/<menu>/<Page>.py        # 导入封装的 py 包

*** Keywords ***
SRAF.<menu>.<Page>.关键字
    <python_def>    ${KDP_VAR_1}    ${KDP_VAR_1}

在 pages 目录中按照页面元素封装功能

pages/<menu>/<Page>.py

from common.Browser import Browser
from common import elePages


class PageName(object):
    def __init__(self):
        self.browser = Browser()

    def login_kdp(self, user: str, password: str):
        self.browser.input_text(
            page=elePages.menu1.Page1(),
            key=u'登录名',
            value=user
        )
        self.browser.input_text(
            page=elePages.menu1.Page1(),
            key=u'密码',
            value=password
        )
        self.browser.click_button(
            page=elePages.menu1.Page1(),
            key=u'登录'
        )

    def upload_file(self):
        self.browser.upload_file(
            page=elePages.menu2.Page4(),
            key=u'上传附件',
            value='/workspace/demo_attach.png'
        )
在 elements 目录中存储页面元素的 xpath

elements/<menu>/<Page>.yaml

元素名称: 'xpath'
持续集成

在安装了 Docker 和 Allure 插件的 Jenkins 上,通过参数构建灵活的启动。依旧没有套路,贴心的为大家留下 Jenkinsfile 在代码仓库的根目录中

pipeline {
  agent any
  environment {
    DOCKER_REGISTRY='registry.cn-hangzhou.aliyuncs.com'
  }
  parameters {
    string name: 'GIT_HTTP_URL', trim: true, defaultValue: 'https://github.com/seoktaehyeon/sraFramework.git'
    string name: 'GIT_BRANCH_NAME', trim: true, defaultValue: 'develop'
    string name: 'GIT_CRED', trim: true, defaultValue: 'sraf-devops'
    string name: 'RF_CONFIG', trim: true, defaultValue: 'template.yaml'
    string name: 'RF_TAG', trim: true, defaultValue: 'Demo'
  }
  stages {
    stage('Git Clone') {
      steps {
        deleteDir()
        checkout([
          $class: 'GitSCM',
          branches: [[name: "$GIT_BRANCH_NAME"]],
          doGenerateSubmoduleConfigurations: false,
          extensions: [],
          submoduleCfg: [],
          userRemoteConfigs: [[
            credentialsId: "$GIT_CRED",
            url: "$GIT_HTTP_URL"
          ]]
        ])
      }
    }
    stage('Execute Test Case') {
      steps {
        withDockerContainer(
          image: "${DOCKER_REGISTRY}/bxwill/robotframework:py-chrome-allure",
          args: '--shm-size=1g'
        ) {
          sh """
          ./sraf-cmd --report jenkins-allure --config config/${RF_CONFIG} --tag ${RF_TAG}
          """
        }
      }
      post {
        always {
          allure includeProperties: false, results: [[path: 'output/allure-results']]
        }
      }
    }
  }
}

流水线执行所在的容器环境也已经为大家构建奉上。无论是官网的 bxwill/robotframework:py-chrome-allure 还是阿里云上的 registry.cn-hangzhou.aliyuncs.com/bxwill/robotframework:py-chrome-allure,一些依赖包都已安装完成,开箱即用。

甚至,若是想在 GitHub 的 workflow 里跑一下,也可行。.github/workflows/executor.yaml 就乖乖的在代码仓库中,大家也可以直接点击进入 GitHub 的 workflows 链接瞄一眼。

图片

图片

图片

测试报告

爱美之心人皆有之,有一份漂亮的测试报告展示一下,多少还是要涨点脸的,该方案中引入了 Allure 报告框架,执行完成后,可以打开一份 HTML 的报告。

一打开报告,配色就比大多数的测试报告要协调很多,一些重要信息直接映入眼帘,即使读者不是测试工程师,也能看出个所以然来。

图片

用中文关键字表示测试步骤,冲破语言障碍。

图片

虽然是在一个没有图形化界面的容器中执行,但使用谷歌的 headless 模式启动 Chrome,网页元素还是加载渲染的,对关键操作进行截图自然不在话下。

图片

总结

花眼的技术千篇一律,落地的方案万里挑一。该方案经过几个产品的套用,如今我把它脱敏提炼,免费送给大家,如果你能看出其中的价值,觉得有用,不妨点个赞。

方案在落地的时候,终归还是不可能一尘不变的,没有最佳方案,只有最适合的方案。