安装包
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主页,点击插件管理,高级选项最后面
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的下载
<mirror>
<id>szxy1</id>
<mirrorOf>*,!central</mirrorOf>
<url>https://mirrors.tools.xxxxxx.com/artifactory/sz-maven-public/ </url>
</mirror>
安装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)
public static WebDriver getDriver() throws IOException { File directory = new File("");//参数为空 String courseFile = directory.getCanonicalPath() ; ChromeOptions chromeOptions = new ChromeOptions(); if (System.getProperty("os.name").contains("Windows")) { System.setProperty("webdriver.chrome.driver", courseFile + "/src/test/resources/chromedriver.exe"); } else { System.setProperty("webdriver.chrome.driver", courseFile + "/src/test/resources/chromedriver"); chromeOptions.addArguments("-headless"); chromeOptions.addArguments("-no-sandbox"); } return new ChromeDriver(chromeOptions); }
由于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
import osHOME = os.path.join("/", "disk2", "jenkinsCodeRepository", "ITData")TEST_HOME = os.path.join("/", "disk2", "jenkinsCodeRepository", "ITdata-Auto-Test")TEST_FINISHED_KEYWORD = r"Finished at"ALLURE = "allure"ALLURE_LOG_FILENAME = "allure.txt"ALLURE_COMMEND = r"nohup allure serve target/surefire-reports -p 4567 >" + ALLURE_LOG_FILENAME + " 2>&1 &"ALLURE_SUCCESS_KEYWORD = r"Server started at"ALLURE_EXIST_KEYWORD = ".*allure.CommandLine serve target/surefire-reports -p 4567"ALLURE_LOG_FILE_PATH = os.path.join(TEST_HOME, ALLURE_LOG_FILENAME)JAVA = "java"JAVA_LOG_FILENAME = "service.txt"JAVA_COMMEND = r"nohup java -jar target/xxx-1.0.0.jar >" + JAVA_LOG_FILENAME + " 2>&1 &"JAVA_SUCCESS_KEYWORD = r"Started ApplicationRunner in"JAVA_EXIST_KEYWORD = "java -jar target/xxx-1.0.0.jar"JAVA_HOME = os.path.join(HOME, "xxx")JAVA_LOG_FILE_PATH = os.path.join(JAVA_HOME, JAVA_LOG_FILENAME)WEB = "web"WEB_LOG_FILENAME = "web.txt"WEB_COMMEND = r"nohup npm run dev >" + WEB_LOG_FILENAME + " 2>&1 &"WEB_SUCCESS_KEYWORD = "Network: http://\d+\.\d+\.\d+\.\d+:\d+"WEB_EXIST_KEYWORD = "node\s.*xxx.*vue-cli-service\sserve"WEB_HOME = os.path.join(HOME, "xxx")WEB_LOG_FILE_PATH = os.path.join(WEB_HOME, WEB_LOG_FILENAME)
start_server.py
import osimport reimport sysimport subprocessimport timefrom close_server import close_server, find_server_pidfrom config import JAVA, ALLURE, WEB, ALLURE_COMMEND, JAVA_COMMEND, WEB_COMMEND, \ JAVA_HOME, WEB_HOME, TEST_HOME, JAVA_LOG_FILE_PATH, WEB_LOG_FILE_PATH, \ ALLURE_LOG_FILE_PATH, JAVA_SUCCESS_KEYWORD, WEB_SUCCESS_KEYWORD, ALLURE_SUCCESS_KEYWORDdef start_server(server_name): if find_server_pid(server_name) != -1: print(f"{server_name} server is running.") return False if server_name == ALLURE: commend = ALLURE_COMMEND directory = TEST_HOME log_path = ALLURE_LOG_FILE_PATH elif server_name == JAVA: commend = JAVA_COMMEND directory = JAVA_HOME log_path = JAVA_LOG_FILE_PATH elif server_name == WEB: commend = WEB_COMMEND directory = WEB_HOME log_path = WEB_LOG_FILE_PATH else: raise ValueError(f"We can't start {server_name} server, {JAVA}, {ALLURE}, {WEB} are allowed to " f"be started.") del_log_file(server_name) subprocess.Popen(commend, cwd=directory, shell=True, env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) log_file_exist = False end_time = time.time() + 60 while time.time() <= end_time: if os.path.exists(log_path): log_file_exist = True print(f"Succeeded to create {server_name} server's log file,details in log file path {log_path}") break time.sleep(5) if not log_file_exist: raise FileExistsError(f"Failed to create {server_name} server's log file,log file path {log_path}") start_sign = False end_time = time.time() + 180 while time.time() <= end_time: if check_server_start(server_name): start_sign = True print(f"Succeeded to start {server_name} server") return True time.sleep(5) if not start_sign: print(f"Failed to start {server_name} server") raise RuntimeError(f"Failed to start {server_name} server") return Falsedef check_server_start(server_name: str): if server_name == ALLURE: log_path = ALLURE_LOG_FILE_PATH keyword = ALLURE_SUCCESS_KEYWORD elif server_name == WEB: log_path = WEB_LOG_FILE_PATH keyword = WEB_SUCCESS_KEYWORD elif server_name == JAVA: log_path = JAVA_LOG_FILE_PATH keyword = JAVA_SUCCESS_KEYWORD else: raise ValueError(f"We can't check {server_name} server, {JAVA}, {ALLURE}, {WEB} are allowed to " f"be checked.") with open(log_path, mode='r', encoding='utf-8') as log_file: text = log_file.readlines() for line in text: if re.search(keyword, line): return True return Falsedef del_log_file(server_name): if server_name == ALLURE: log_path = ALLURE_LOG_FILE_PATH elif server_name == WEB: log_path = WEB_LOG_FILE_PATH elif server_name == JAVA: log_path = JAVA_LOG_FILE_PATH else: raise ValueError(f"We can't del {server_name} log file, {JAVA}, {ALLURE}, {WEB} are allowed to " f"be deleted.") if os.path.exists(log_path): os.remove(log_path) print(f"Succeeded to delete {server_name} log file")if __name__ == "__main__": arguments = sys.argv if len(arguments) > 2: raise ValueError("arguments > 2. not allowed") script_path = arguments[0] if len(arguments) >= 1 else "" service_name = arguments[1] if len(arguments) >= 2 else "" if len(service_name) > 0: start_server(service_name) else: start_server(ALLURE) start_server(WEB) start_server(JAVA)
close_server.py
import osimport reimport sysimport subprocessfrom config import JAVA, ALLURE, WEB, JAVA_EXIST_KEYWORD, WEB_EXIST_KEYWORD, \ ALLURE_EXIST_KEYWORDdef close_server(server_name: str): pid = find_server_pid(server_name) if pid == -1: print(f"{server_name} process not found") return False kill_ret = subprocess.Popen(['kill', '-9', pid], shell=False, env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = kill_ret.communicate() if err: raise Exception(err) print(f"Succeeded to close {server_name} server, pid {pid}") return Truedef find_server_pid(server_name): ps_ret = subprocess.Popen(['ps', '-ef'], shell=False, env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = ps_ret.communicate() if err: raise Exception(err) data = out.decode('utf8').split('\n') pid = -1 if server_name == ALLURE: keyword = ALLURE_EXIST_KEYWORD elif server_name == WEB: keyword = WEB_EXIST_KEYWORD elif server_name == JAVA: keyword = JAVA_EXIST_KEYWORD else: raise ValueError(f"We can't check {server_name} server exist, {JAVA}, {ALLURE}, {WEB} are " f"allowed to be checked exist.") for line in data: search = re.search(keyword, line) if search: pid = line.split()[1] break if pid == -1: return pid else: return pid if __name__ == "__main__": arguments = sys.argv if len(arguments) > 2: raise ValueError("arguments > 2. not allowed") script_path = arguments[0] if len(arguments) >= 1 else "" service_name = arguments[1] if len(arguments) >= 2 else "" if len(service_name) > 0: close_server(service_name) else: close_server(ALLURE) close_server(WEB) close_server(JAVA)
2. 脚本启动测试
start_test.py
import osimport reimport subprocessfrom config import JAVA, ALLURE, WEB, TEST_HOME, TEST_FINISHED_KEYWORDfrom close_server import close_serverfrom start_server import start_serverif __name__ == "__main__": start_server(JAVA) start_server(WEB) test_ret = subprocess.Popen(['mvn', 'test'], cwd=TEST_HOME, shell=False, env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = test_ret.communicate() finish_test_sign = False for line in out.decode().split('\n'): if re.search(TEST_FINISHED_KEYWORD, line): finish_test_sign = True print(f"Finish test") break if not finish_test_sign: print(f"Not finish test") raise RuntimeError(err) close_server(JAVA) 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文件。