• jenkins+junit4+allure+selenium实现自动化测试与结果可视化


    安装包

    jenkins.war

    jdk-8u332-linux-x64.tar.gz

    https://repo1.maven.org/maven2/io/qameta/allure/allure-commandline/2.17.2/      allure-commandline-2.17.2.zip

    https://chromedriver.storage.googleapis.com/index.html    chromedriver

    安装JDK

    解压    tar xvf jdk-8u332-linux-x64.tar.gz 

    打开文件    vim /etc/profile

    写入一下内容

    export JAVA_HOME=/usr/jdk // maven会默认读取系统的JAVA_HOME来使用

    export PATH=$PATH:$JAVA_HOME/bin

    关闭vim

    使全局配置生效  source /etc/profile

    jenkins

    1. 运行jenkins

    nohup java -jar -Dhudson.model.DownloadService.noSignatureCheck=true jenkins.war >out.txt 2>&1 &

    -Dhudson.model.DownloadService.noSignatureCheck=true // 表示不验证签名

    nohup // 表示后台运行

    访问:http://jenkins安装机器的ip:8080

    用户名:admin

    密码:在安装过程中会打印在屏幕中,如果没看到,去jenkins/secrets/initialAdminPassword中去找

    如果是war包启动的jenkins,请在/root/.jenkins/secrets/initialAdminPassword中找

    首次登录一定要修改密码,因为初始密码很难记

    2. jenkins配置免密登陆(可选)

    先记录下一个jenkins设置免密登录方法,以备不时之需吧。

    进入Jenkins根目录,如果是war包启动,则应该在/root/.jenkins文件夹下,备份 config.xml 为 config.xml.bak,而后打开 config.xml 配置文件。

    修改“< useSecurity >true< /useSecurity >”为“< useSecurity>false< /useSecurity>”;

    重启jenkins

    3. jenkins插件安装配置

    进入Jenkins主页,点击插件管理,高级选项最后面

    git

    yum install git

    git config --global http."sslVerify" false  // 配置git不校验ssl

    maven

    1. 安装

    下载地址:https://maven.apache.org/download.cgi

    tar -zxvf apache-maven-3.8.5-bin.tar.gz // 解压

    修改全局变量

    vi /etc/profile

    export MAVEN_HOME=/usr/local/maven/apache-maven-3.8.5
    export PATH=$MAVEN_HOME/bin:$PATH

    重新加载全局变量

    source /etc/profile

    测试mvn是否装好

    mvn -v

    另外还需要自行配置maven的配置文件,包括本地仓地址、镜像源等

    2. 配置maven文件

    修改/disk1/apache-maven-3.8.6/conf/settings.xml,一定要加入下面的镜像,涉及关键包ump-client的下载

                    szxy1

                    *,!central

                    https://mirrors.tools.xxxxxx.com/artifactory/sz-maven-public/

                 

    安装Allure

    解压allure-commandline-2.17.2.zip安装包,将bin目录加入到系统的全局变量中

    修改全局变量

    vi /etc/profile

    export PATH=/disk2/jenkinsCodeRepository/allure/allure-2.17.2/bin:$PATH

    重新加载全局变量

    source /etc/profile

    测试mvn是否装好

    allure --version

    nodejs

    1. 下载安装

    Index of /dist/去寻找自己想要的版本

    我下载的是node-v16.14.2-linux-x64.tar.xz

    tar xvf node-v16.14.2-linux-x64.tar.xz

    vi /etc/profile // 修改环境变量

    在最后加上:

    export NODE_HOME= /disk1/nodejs/node-v16.14.2-linux-x64

    export PATH=$NODE_HOME/bin:$PATH

    再执行 source /etc/profile  让环境变量生效;

    检查是否安装成功:

    node –v

    npm -v

    2. 回退npm版本到指定版本

    npm set strict-ssl false  // 设置不校验ssl

    npm config set registry https://npm.inxxxxxx.com/  // 配置源镜像地址

    npm install npm@6.14.13 –g  // 下载新的npm包

    3. 下载依赖

    npm install --unsafe-perm=true --allow-root

    npm 出于安全考虑不支持以 root 用户运行,即使你用 root 用户身份运行了,npm 会自动转成一个叫 nobody 的用户来运行,而这个用户几乎没有任何权限。这样的话如果脚本里有一些需要权限的操作,比如写文件(尤其是写 /root/.node-gyp),就会崩掉。

    为了避免这种情况,要么按照 npm 的规矩来,专门建一个用于运行 npm 的高权限用户;要么加 --unsafe-perm 参数,这样就不会切换到 nobody 上,运行时是哪个用户就是哪个用户,即使是 root。

    在linux中启动谷歌浏览器

    1. 安装

    https://chromedriver.storage.googleapis.com/index.html    chromedriver

    2. Linux需要赋权

    chmod +x chromedriver

    3. 启动网易浏览器驱动(windows,Linux)

    1. public static WebDriver getDriver() throws IOException {
    2. File directory = new File("");//参数为空
    3. String courseFile = directory.getCanonicalPath() ;
    4. ChromeOptions chromeOptions = new ChromeOptions();
    5. if (System.getProperty("os.name").contains("Windows")) {
    6. System.setProperty("webdriver.chrome.driver", courseFile + "/src/test/resources/chromedriver.exe");
    7. }
    8. else {
    9. System.setProperty("webdriver.chrome.driver", courseFile + "/src/test/resources/chromedriver");
    10. chromeOptions.addArguments("-headless");
    11. chromeOptions.addArguments("-no-sandbox");
    12. }
    13. return new ChromeDriver(chromeOptions);
    14. }

      由于Linux服务器有可能是无界面的,所以需要设置额外的参数headless与no-sandbox

    拉取并构建代码

    1. jenkins拉取

    Jenkins创建一个自由项目,Source Code Management里面勾选git表示用git拉取代码,有配置项目用户名密码登录的还需要在Credentials新增一个拉取代码的账号密码,最后在Additional Behaviours加入一个check out to a sub-directory,表示将要把代码拉取到哪个目录下面。

    2. jenkins构建

    后端mvn工程使用mvn -DskipTests=true clean install构建,跳过单元测试代码

    前端vue工程要先cd到项目目录下,然后npm install --unsafe-perm=true,下载前端依赖

    脚本启动自动化测试

    1. 编写python脚本启动待测试工程

    思路:

    1. 使用命令行启动程序,java –jar xxx.jar,   npm run dev,但需要注意加上nohup在后台运行,不然python脚本无法停止,nohup { commend } >running_log.txt 2>&1 &

    第一个>表示把运行过程中控制台的输入也就是输出流打印到后面的文件中,2表示错误信息,&1表示正常输出,2>&1表示无论是命令出问题或者没出问题,都把控制台信息打印到输出流里面,最后一个&是nohup命令的固定格式。

    2. subprocess.popen运行命令,cwd参数指定运行命令的目录,npm run dev只能在工程目录下才能运行。

    3. 检测启动通过检测启动命令重定向的文件,查找关键字。

    4. 关闭工程通过kill -9 {pid},pid通过ps –ef查找,通过关键字筛选。

    config.py

    1. import os
    2. HOME = os.path.join("/", "disk2", "jenkinsCodeRepository", "ITData")
    3. TEST_HOME = os.path.join("/", "disk2", "jenkinsCodeRepository", "ITdata-Auto-Test")
    4. TEST_FINISHED_KEYWORD = r"Finished at"
    5. ALLURE = "allure"
    6. ALLURE_LOG_FILENAME = "allure.txt"
    7. ALLURE_COMMEND = r"nohup allure serve target/surefire-reports -p 4567 >" + ALLURE_LOG_FILENAME + " 2>&1 &"
    8. ALLURE_SUCCESS_KEYWORD = r"Server started at"
    9. ALLURE_EXIST_KEYWORD = ".*allure.CommandLine serve target/surefire-reports -p 4567"
    10. ALLURE_LOG_FILE_PATH = os.path.join(TEST_HOME, ALLURE_LOG_FILENAME)
    11. JAVA = "java"
    12. JAVA_LOG_FILENAME = "service.txt"
    13. JAVA_COMMEND = r"nohup java -jar target/xxx-1.0.0.jar >" + JAVA_LOG_FILENAME + " 2>&1 &"
    14. JAVA_SUCCESS_KEYWORD = r"Started ApplicationRunner in"
    15. JAVA_EXIST_KEYWORD = "java -jar target/xxx-1.0.0.jar"
    16. JAVA_HOME = os.path.join(HOME, "xxx")
    17. JAVA_LOG_FILE_PATH = os.path.join(JAVA_HOME, JAVA_LOG_FILENAME)
    18. WEB = "web"
    19. WEB_LOG_FILENAME = "web.txt"
    20. WEB_COMMEND = r"nohup npm run dev >" + WEB_LOG_FILENAME + " 2>&1 &"
    21. WEB_SUCCESS_KEYWORD = "Network: http://\d+\.\d+\.\d+\.\d+:\d+"
    22. WEB_EXIST_KEYWORD = "node\s.*xxx.*vue-cli-service\sserve"
    23. WEB_HOME = os.path.join(HOME, "xxx")
    24. WEB_LOG_FILE_PATH = os.path.join(WEB_HOME, WEB_LOG_FILENAME)

    start_server.py

    1. import os
    2. import re
    3. import sys
    4. import subprocess
    5. import time
    6. from close_server import close_server, find_server_pid
    7. from config import JAVA, ALLURE, WEB, ALLURE_COMMEND, JAVA_COMMEND, WEB_COMMEND, \
    8. JAVA_HOME, WEB_HOME, TEST_HOME, JAVA_LOG_FILE_PATH, WEB_LOG_FILE_PATH, \
    9. ALLURE_LOG_FILE_PATH, JAVA_SUCCESS_KEYWORD, WEB_SUCCESS_KEYWORD, ALLURE_SUCCESS_KEYWORD
    10. def start_server(server_name):
    11. if find_server_pid(server_name) != -1:
    12. print(f"{server_name} server is running.")
    13. return False
    14. if server_name == ALLURE:
    15. commend = ALLURE_COMMEND
    16. directory = TEST_HOME
    17. log_path = ALLURE_LOG_FILE_PATH
    18. elif server_name == JAVA:
    19. commend = JAVA_COMMEND
    20. directory = JAVA_HOME
    21. log_path = JAVA_LOG_FILE_PATH
    22. elif server_name == WEB:
    23. commend = WEB_COMMEND
    24. directory = WEB_HOME
    25. log_path = WEB_LOG_FILE_PATH
    26. else:
    27. raise ValueError(f"We can't start {server_name} server, {JAVA}, {ALLURE}, {WEB} are allowed to "
    28. f"be started.")
    29. del_log_file(server_name)
    30. subprocess.Popen(commend,
    31. cwd=directory,
    32. shell=True,
    33. env=os.environ,
    34. stdin=subprocess.PIPE,
    35. stdout=subprocess.PIPE,
    36. stderr=subprocess.PIPE)
    37. log_file_exist = False
    38. end_time = time.time() + 60
    39. while time.time() <= end_time:
    40. if os.path.exists(log_path):
    41. log_file_exist = True
    42. print(f"Succeeded to create {server_name} server's log file,details in log file path {log_path}")
    43. break
    44. time.sleep(5)
    45. if not log_file_exist:
    46. raise FileExistsError(f"Failed to create {server_name} server's log file,log file path {log_path}")
    47. start_sign = False
    48. end_time = time.time() + 180
    49. while time.time() <= end_time:
    50. if check_server_start(server_name):
    51. start_sign = True
    52. print(f"Succeeded to start {server_name} server")
    53. return True
    54. time.sleep(5)
    55. if not start_sign:
    56. print(f"Failed to start {server_name} server")
    57. raise RuntimeError(f"Failed to start {server_name} server")
    58. return False
    59. def check_server_start(server_name: str):
    60. if server_name == ALLURE:
    61. log_path = ALLURE_LOG_FILE_PATH
    62. keyword = ALLURE_SUCCESS_KEYWORD
    63. elif server_name == WEB:
    64. log_path = WEB_LOG_FILE_PATH
    65. keyword = WEB_SUCCESS_KEYWORD
    66. elif server_name == JAVA:
    67. log_path = JAVA_LOG_FILE_PATH
    68. keyword = JAVA_SUCCESS_KEYWORD
    69. else:
    70. raise ValueError(f"We can't check {server_name} server, {JAVA}, {ALLURE}, {WEB} are allowed to "
    71. f"be checked.")
    72. with open(log_path, mode='r', encoding='utf-8') as log_file:
    73. text = log_file.readlines()
    74. for line in text:
    75. if re.search(keyword, line):
    76. return True
    77. return False
    78. def del_log_file(server_name):
    79. if server_name == ALLURE:
    80. log_path = ALLURE_LOG_FILE_PATH
    81. elif server_name == WEB:
    82. log_path = WEB_LOG_FILE_PATH
    83. elif server_name == JAVA:
    84. log_path = JAVA_LOG_FILE_PATH
    85. else:
    86. raise ValueError(f"We can't del {server_name} log file, {JAVA}, {ALLURE}, {WEB} are allowed to "
    87. f"be deleted.")
    88. if os.path.exists(log_path):
    89. os.remove(log_path)
    90. print(f"Succeeded to delete {server_name} log file")
    91. if __name__ == "__main__":
    92. arguments = sys.argv
    93. if len(arguments) > 2:
    94. raise ValueError("arguments > 2. not allowed")
    95. script_path = arguments[0] if len(arguments) >= 1 else ""
    96. service_name = arguments[1] if len(arguments) >= 2 else ""
    97. if len(service_name) > 0:
    98. start_server(service_name)
    99. else:
    100. start_server(ALLURE)
    101. start_server(WEB)
    102. start_server(JAVA)

    close_server.py

    1. import os
    2. import re
    3. import sys
    4. import subprocess
    5. from config import JAVA, ALLURE, WEB, JAVA_EXIST_KEYWORD, WEB_EXIST_KEYWORD, \
    6. ALLURE_EXIST_KEYWORD
    7. def close_server(server_name: str):
    8. pid = find_server_pid(server_name)
    9. if pid == -1:
    10. print(f"{server_name} process not found")
    11. return False
    12. kill_ret = subprocess.Popen(['kill', '-9', pid],
    13. shell=False,
    14. env=os.environ,
    15. stdin=subprocess.PIPE,
    16. stdout=subprocess.PIPE,
    17. stderr=subprocess.PIPE)
    18. out, err = kill_ret.communicate()
    19. if err:
    20. raise Exception(err)
    21. print(f"Succeeded to close {server_name} server, pid {pid}")
    22. return True
    23. def find_server_pid(server_name):
    24. ps_ret = subprocess.Popen(['ps', '-ef'],
    25. shell=False,
    26. env=os.environ,
    27. stdin=subprocess.PIPE,
    28. stdout=subprocess.PIPE,
    29. stderr=subprocess.PIPE)
    30. out, err = ps_ret.communicate()
    31. if err:
    32. raise Exception(err)
    33. data = out.decode('utf8').split('\n')
    34. pid = -1
    35. if server_name == ALLURE:
    36. keyword = ALLURE_EXIST_KEYWORD
    37. elif server_name == WEB:
    38. keyword = WEB_EXIST_KEYWORD
    39. elif server_name == JAVA:
    40. keyword = JAVA_EXIST_KEYWORD
    41. else:
    42. raise ValueError(f"We can't check {server_name} server exist, {JAVA}, {ALLURE}, {WEB} are "
    43. f"allowed to be checked exist.")
    44. for line in data:
    45. search = re.search(keyword, line)
    46. if search:
    47. pid = line.split()[1]
    48. break
    49. if pid == -1:
    50. return pid
    51. else:
    52. return pid
    53. if __name__ == "__main__":
    54. arguments = sys.argv
    55. if len(arguments) > 2:
    56. raise ValueError("arguments > 2. not allowed")
    57. script_path = arguments[0] if len(arguments) >= 1 else ""
    58. service_name = arguments[1] if len(arguments) >= 2 else ""
    59. if len(service_name) > 0:
    60. close_server(service_name)
    61. else:
    62. close_server(ALLURE)
    63. close_server(WEB)
    64. close_server(JAVA)

    2. 脚本启动测试

    start_test.py

    1. import os
    2. import re
    3. import subprocess
    4. from config import JAVA, ALLURE, WEB, TEST_HOME, TEST_FINISHED_KEYWORD
    5. from close_server import close_server
    6. from start_server import start_server
    7. if __name__ == "__main__":
    8. start_server(JAVA)
    9. start_server(WEB)
    10. test_ret = subprocess.Popen(['mvn', 'test'],
    11. cwd=TEST_HOME,
    12. shell=False,
    13. env=os.environ,
    14. stdin=subprocess.PIPE,
    15. stdout=subprocess.PIPE,
    16. stderr=subprocess.PIPE)
    17. out, err = test_ret.communicate()
    18. finish_test_sign = False
    19. for line in out.decode().split('\n'):
    20. if re.search(TEST_FINISHED_KEYWORD, line):
    21. finish_test_sign = True
    22. print(f"Finish test")
    23. break
    24. if not finish_test_sign:
    25. print(f"Not finish test")
    26. raise RuntimeError(err)
    27. close_server(JAVA)
    28. close_server(WEB)

    jenkins配置allure

    1. 安装插件

     2. jenkins的project配置

    在build选项卡中新增命令,先删除原来存留的测试结果,然后把新的测试结果文件移动到jenkins的allure工作目录下,文件夹名称一定要命名为allure-results,最后在post-build中配置测试结果文件夹的相对路径,就是刚刚移动文件到的allure-results文件夹。

    我是用的是java的junit4+allure,生成测试结果文件通常保存在./在工程目录/target/surefire-reports文件夹中,python的话应该是一堆json文件。

  • 相关阅读:
    Springboot-热部署-IDEA2023
    报道 | 8月国际运筹优化会议汇总
    中英文双语言海外微盘交易源码 微盘交易源码 虚拟币微盘交易系统源码 支持产品数据
    动态规划法——递进式教你运用代码题解《买卖股票的最好时机》
    C++ 命名空间-----namespace(超详细解析,小白必看系列)
    零样本和少样本学习
    使用GitHub Actions实现自动化部署
    ZYNQ RFSoc开发板-usrp软件无线电X410mini开发板-5G评估板
    14数据结构与算法刷题之【深搜&宽搜递归&分治&剪枝回溯】篇
    spring框架
  • 原文地址:https://blog.csdn.net/weixin_40292043/article/details/127736822