需求 & 背景
将自动化测试集成到Jenkins中,最终实现每次构建部署时自动完成基础测试。
因为在日常的部署中,有出现Pod和容器正常启动,但运行报错,导致服务不可用的情况。而CI/CD的频率较高,单个项目一天可能更新三到四次,从成本角度来说无法实现每次更新后都有测试工程师进行覆盖。这种情况从运维角度来解决无非是监控指定端口能否访问,但这样实际是脱离业务的,毕竟如果用户访问不了,一切白搭。
翻看了百度和Google的资料,并没有发现能解决该痛点的解决方案。最常见的方案通常是测试工程师从他们的windows本机部署Jenkins使用脚本来完成测试(环境在本机已经配置好)。参考过同事,他那边是使用gitlab-runner来提供python的运行环境,所以也曾发散想过是否能通过Jenkins-Node节点的方式来实现。后来发现即使是使用Node,那也得Node有python环境也需要我手动来装,那不如就直接装进主节点。
所以打算将运维和测试进行结合,部署后只保证服务基本能访问,剩下的功能、接口测试由专业的测试工程师解决。
介绍
本质其实也是Jenkins执行shell命令,只不过Jenkins是部署在服务器中。所以在Jenkins容器中安装需要的python环境。如果是以K8S形式部署,接下来我会将实现步骤打包成Docker镜像。列出本次自动化测试中用到的软件及三方库介绍:
Jenkins
开源的CI/CD自动化平台。
pytest
Python的一款开源单元测试框架。
selenium
开源的web自动化工具,模拟用户在浏览器中进行操作。
Chromedriver 是 Chrome 驱动,是 Python 爬虫使用的 selenium 模块用来模拟打开谷歌浏览器所必须的一个文件,能模拟在谷歌浏览器上的操作。
allure
开源的测试报告框架,用于生成测试报告,与pytest配合效果奇佳。
使用
使用流程如下:
- 编写自动化测试用例(本人只写了一个,就是通过selenium来测试平台能否正常访问);
- 将含测试用例的目录推送到Jenkins容器中(不管以gitlab还是以链接的形式);
- 安装运行环境,运行测试用例进行测试;
- 通过Jenkins-UI编写执行脚本;
- Jenkins下载allure插件并配置,使其自动生成测试报告;
测试用例编写
pytest/ # 项目目录结构
├── config
│ └── yaml_load.py # 封装配置文件函数
├── data
│ └── login.yaml # 登录账号密码
└── test_login.py # 测试用例,实现功能:链接指定网站,输入账号密码并登录
$ cat pytest/data/login.yaml # 登录账号密码
-
user: root
pwd: xxxxxxxx
$ cat pytest/config/yaml_load.py # 封装配置文件函数
import yaml
def load_yaml(filename):
stream = open(filename, 'r')
data = yaml.load(stream, yaml.FullLoader)
return data
$ cat pytest/test_login.py # 测试用例
import pytest
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from config.yaml_load import load_yaml
class Testcase:
# 登录
def setup(self):
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless") # 无头模式
chrome_options.add_argument("--no-sandbox") # 沙盒模式
chrome_options.add_argument("--incognito") # 无痕模式
self.driver = webdriver.Chrome(options=chrome_options)
self.driver.get('http://ebox.wlhiot.com/login?redirect=%2Fhome')
# 关闭浏览器
def teardown(self):
self.driver.quit()
@pytest.mark.parametrize('udata', load_yaml('./data/login.yaml'))
def test_01(self, udata):
self.driver.find_element(By.XPATH, '//*[@id="app"]/div/form/div[1]/div/div/input').send_keys(udata['user'])
self.driver.find_element(By.XPATH, '//*[@id="app"]/div/form/div[2]/div/div[1]/input').send_keys(udata['pwd'])
self.driver.find_element(By.CLASS_NAME, 'el-button--primary').click()
time.sleep(2)
a = self.driver.current_url # 获取点击确认后的url
b = 'http://ebox.wlhiot.com/home' # 正确输入密码跳转的页面
assert a == b # 断言,若符合预期则测试通过,不符合预期则报错
if __name__ == '__main__':
# pytest.main(['-s', 'test_login.py', '--alluredir', './allure-results', '--clean'])
pytest.main(['-s', 'test_login.py'])
Jenkins部署
docker run -d -p 8005:8080 --name jenkins-server \
--shm-size="500M" \ # 由于jenkins的/dev/shm分区默认只有64M,在UI自动化测试时会因为内存不足导致页面崩溃
-v /etc/localtime:/etc/localtime:ro \ # 时间与本机一致
-v /usr/local/wlhiot/mount/jenkins:/var/jenkins_home \ # 数据目录,只要复制该目录即可实现数据的迁移
-v /usr/bin/docker:/usr/bin/docker \ # 根据需要,使Jenkins也能实现docker命令
-v /var/run/docker.sock:/var/run/docker.sock \ # 根据需要,使Jenkins也能实现docker命令
jenkins/jenkins # 官方镜像,原jenkins已经弃用
docker exec -it -uroot jenkins-server /bin/bash # 使用root命令登录
权限管理
实现Jenkins用户可以使用root权限执行命令,否则测试用例无法正常运行
mv /etc/sudoers /var/jenkins_home/
vim /usr/local/wlhiot/mount/jenkins/sudoers # 将Jenkins容器的/etc/sudoers文件迁移至/varjenkins_home/sudoers,通过宿主机添加如下两行
jenkins ALL=(ALL) ALL
jenkins ALL=(ALL) NOPASSWD: ALL
mv /var/jenkins_home/sudoers /etc/
python环境
总是觉得该方法太过复杂,若有更方便的方式可同作者联系wechat ID : Daihr2333
cd /usr/local/src;wget https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tgz # 若无法下载可以本机下载后存放在服务器的/usr/local/wlhiot/mount/jenkins目录,然后从容器/var/jenkins_home/目录即可找到
tar -xzvf Python-3.8.13.tgz
cd Python-3.8.13
apt-get -y install gcc automake autoconf libtool make # 可能由于网络问题中断,记得要全部下载后再编译安装
apt-get -y install make* # Jenkins容器的镜像是debian系,所以使用apt-get命令下载
apt-get -y install zlib*
apt-get -y install openssl libssl-dev
apt-get install sudo
cd /usr/local/src;wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz # python3.8需要高版本的openssl
tar -zxvf openssl-1.1.1a.tar.gz
cd openssl-1.1.1a
./config --prefix=/usr/local/openssl no-zlib
make && make install
mv /usr/bin/openssl /usr/bin/openssl.bakmv /usr/bin/openssl /usr/bin/openssl.bak
mv /usr/bin/openssl /usr/bin/openssl.bak
ln -s /usr/local/openssl/include/openssl /usr/include/openssl
ln -s /usr/local/openssl/lib/libssl.so.1.1 /usr/local/lib64/libssl.so
ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
echo "/usr/local/openssl/lib" >> /etc/ld.so.conf # 羞辱openssl库文件的搜索路径
ldconfig -v # 使修改后的/etc/ld.so.conf生效
openssl version # 查看openssl版本
./configure --prefix=/usr/local/src/py3.8 --with-ssl && make && make install
ln -s /usr/local/src/py3.8/bin/python3.8 /usr/bin/python3 # 使用python3 -V验证
ln -s /usr/local/src/py3.8/bin/pip3 /usr/bin/pip3 # 使用pip3验证
pytest环境
cat /root/requirements.txt # 也可在服务器端将文件挂载进容器
allure-pytest==2.9.45
allure-python-commons==2.9.45
async-generator==1.10
attrs==21.4.0
certifi==2022.5.18.1
cffi==1.15.0
charset-normalizer==2.0.12
cryptography==37.0.2
h11==0.13.0
idna==3.3
iniconfig==1.1.1
outcome==1.1.0
packaging==21.3
pluggy==1.0.0
py==1.11.0
pycparser==2.21
pyOpenSSL==22.0.0
pyparsing==3.0.9
PySocks==1.7.1
pytest==7.1.2
PyVirtualDisplay==3.0
PyYAML==6.0
requests==2.27.1
selenium==4.2.0
six==1.16.0
sniffio==1.2.0
sortedcontainers==2.4.0
tomli==2.0.1
trio==0.21.0
trio-websocket==0.9.2
urllib3==1.26.9
wsproto==1.1.0
pip3 install --upgrade pip # 更新pip版本
pip3 install -Ur /root/requirements.txt # 下载所需三方库,可根据实际需要下载
chrome及chromedriver
wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
apt-get -y update
apt-get -y install google-chrome-stable
/usr/bin/google-chrome-stable --version # 查看schrome版本
wget https://chromedriver.storage.googleapis.com/102.0.5005.61/chromedriver_linux64.zip
ls # 根据chrome版本下载对应的chromedriver版本
unzip chromedriver_linux64.zip # 解压后就一个可执行文件,将可执行文件录入环境变量即可
mv chromedriver /usr/local/src/3.8/bin/
ln -s /usr/local/src/3.8/bin/chromedriver /usr/bin/chromedriver
运行测试用例
cd /var/jenkins_home/pytest # 切换到项目目录
sudo python3 -m pytest -s --junit-xml=result.xml --alluredir /var/jenkins_home/workspace/Dir_wlh_project_test_k8s/ebox_svr_test_k8s/wlh-electric/target/allure-results --clean-alluredir
# workspace后的路径根据实际情况调整,使用该命令会生成测试用例的运行结果,能出现allure-results目录说明运行成功,该目录保存测试结果
集成(通过Jenkins-UI)
整套测试流程能跑通之后,就可以将运行测试用例的操作集成到Jenkins中以实现自动化。
插件安装
安装allure插件
点击'配置',进入'全局配置',新增Allure Commandline
修改Job配置
执行shell命令
#!/bin/bash
/bin/sleep 10 # 等服务正式部署后再进行测试,所以先等一会儿
cd /var/jenkins_home/pytest # 切换到pytest项目路径
sudo python3 -m pytest -s --junit-xml=result.xml --alluredir /var/jenkins_home/workspace/Dir_wlh_project_test_k8s/ebox_svr_test_k8s/wlh-electric/target/allure-results --clean-alluredir
sudo chown jenkins.jenkins /var/jenkins_home/workspace/Dir_wlh_project_test_k8s/ebox_svr_test_k8s/wlh-electric/target/allure-results -R # 修改权限,否则allure插件无法读取allure-resuluts
exit 0
调整allure配置
读取的results是以相对路径的方式,若是正常的项目一般是target/allure-results。因为我方项目是多个微服务项目集成的,所以还另加了wlh-electric作为前缀。
报告输出的路径则直接存放至相对路径的顶级目录,以我方的路径是/var/jenkins_home/workspace/Dir_wlh_project_test_k8s/ebox_svr_test_k8s/allure-reports。