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

news2025/7/13 16:46:19

安装包

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的下载

<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 os

HOME = 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 os
import re
import sys
import subprocess
import time

from close_server import close_server, find_server_pid
from 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_KEYWORD


def 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 False


def 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 False


def 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 os
import re
import sys
import subprocess

from config import JAVA, ALLURE, WEB, JAVA_EXIST_KEYWORD, WEB_EXIST_KEYWORD, \
    ALLURE_EXIST_KEYWORD


def 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 True


def 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 os
import re
import subprocess

from config import JAVA, ALLURE, WEB, TEST_HOME, TEST_FINISHED_KEYWORD
from close_server import close_server
from start_server import start_server

if __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文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8682.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

优盘数据恢复如何操作?恢复U盘数据的三个简单方法

对于我们用户来说&#xff0c;经常使用U盘来存储一些重要的文件是很常见的事。很多用户在使用的时候&#xff0c;经常因为操作不规范&#xff0c;而造成一些数据丢失。那么我们该如何做呢&#xff1f;优盘数据恢复如何操作&#xff1f;今天小编就来为大家分享一下关于如何将U盘…

基于梯度的图像边缘检测

参考视频&#xff1a;https://www.bing.com/videos/search?qacomputationalapproachtoedgedetection&docid608014236869751913&mid8C04384FFDD6A47533238C04384FFDD6A4753323&viewdetail&FORMVIRE 参考文献&#xff1a;A Computational Approach to Edge Dete…

【图像去噪】基于空间光谱总变化减少高光谱图像的混合噪声(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

线程的“打断”

【打断线程的三个方法】&#xff1a; //Thread.java public void interrupt() //t.interrupt() 打断t线程&#xff08;设置t线程某给标志位ftrue&#xff0c;并不是打断线程的运行&#xff09; public boolean isInterrupted() //t.isInterrupted() 查询打…

线程池源码解析 1.前导_FutureTask源码解析

线程池—FutureTask源码解析 简介 在学习线程池之前&#xff0c;需要先学习一下 FutureTask&#xff0c;因为线程池 submit 的结果就是 FutureTask。 那么什么是 FutureTask&#xff0c;其表示一个未来的任务。也就是说这个任务比较耗时&#xff0c;当前调用线程会阻塞拿到这…

某程序员发现 CSDN官方“漏洞”,立省¥10000+,抓紧薅吧

是一个省钱的组织&#xff01;&#xff01;&#xff01;它叫做勤学会&#xff0c;CSDN 官方背书。 打开这篇博客&#xff0c;你首先就要面对一个问题。 勤学会到底是什么&#xff1f;活动&#xff1f;社区&#xff1f;还是一个名词。 今天这篇博客就从解释【勤学会】这三个字开…

【Wins+VSCode】配置C++开发环境

目录1、安装vscode2、安装中文包和c扩展包3、安装c编译工具&#xff1a;g4、运行代码测试5、lauch.json6、tasks.json7、问题7.1、找不到gcc任务Reference1、安装vscode 官网下载就可以了&#xff0c;免费的&#xff1a; https://code.visualstudio.com/ 2、安装中文包和c扩展…

【Java项目】讲讲我用Java爬虫获取LOL英雄数据与图片(附源码)

&#x1f680;用Java爬一下英雄联盟数据 &#x1f4d3;推荐网站(不断完善中)&#xff1a;个人博客 &#x1f4cc;个人主页&#xff1a;个人主页 &#x1f449;相关专栏&#xff1a;CSDN专栏 &#x1f3dd;立志赚钱&#xff0c;干活想躺&#xff0c;瞎分享的摸鱼工程师一枚 &…

【Asesprite】快速自制Tileset瓦片地图集(俯视角)

使用Aseprite软件完成一个Tileset素材的制作&#xff0c;用于2D游戏开发。 目录 一、基础配置 二、草地和泥土 三、导出为TileSet素材 一、基础配置 1.创建一个96x48的画布。 2.在菜单中选择View-》GridSettings。 3.设置网格宽高为16x16。 4.点击View-》Show-》Grid显…

IOS手机和车机互联自动化测试

在酷热的夏天&#xff0c;提前打开空调&#xff1b;在寒冷的冬天&#xff0c;提前加热座椅和方向盘。这些贴心的功能都是通过手机远程控制汽车实现的。随着汽车新四化的进程推进&#xff0c;类似手机和车机连接的功能必然越来越多。 作为汽车行业的工程师&#xff0c;我们都知道…

Jenkins 忘记登录密码解决办法

今天给大家分享下 jenkins 登录密码忘记的解决办法&#xff0c;方法不唯一&#xff0c;都能解决问题&#xff0c;按照自己的习惯来做更好。 1、先停止 jenkins 服务 systemctl stop jenkins 此步骤可以结合 ps -ef | grep jenkins 和 kill -9 jenkins进程号 一起解决2、找到…

简单实用的Python图像处理库Pillow

Pillow图像处理Pillow 库的安装图象处理基本知识图像的RGB 色彩模式像素阵列Image 模块打开和新建混合透明度混合处理遮罩混合处理复制和缩放复制图像缩放像素缩放图像粘贴和裁剪粘贴裁剪图像图像旋转格式转换covert()transpose()分离和合并分离合并滤镜其他内置函数ImageFilte…

A Blockchain-Driven IIoT Traffic Classification Service for Edge Computing 论文学习

A Blockchain-Driven IIoT Traffic Classification Service for Edge Computing IEEE INTERNET OF THINGS JOURNAL&#xff0c;2021 文章目录A Blockchain-Driven IIoT Traffic Classification Service for Edge ComputingSummaryResearch Objective(s)Background / Problem S…

用Canvas绘制一个数字键盘

Hello啊老铁们&#xff0c;这篇文章还是阐述自定义View相关的内容&#xff0c;用Canvas轻轻松松搞一个数字键盘&#xff0c;本身没什么难度&#xff0c;这种效果实现的方式也是多种多样&#xff0c;这篇只是其中的一种&#xff0c;要说本篇有什么特别之处&#xff0c;可能就是纯…

OpenGL 灰度图

目录 一.OpenGL 灰度图 1.IOS Object-C 版本1.Windows OpenGL ES 版本2.Windows OpenGL 版本 二.OpenGL 灰度图 GLSL Shader三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 &…

振弦采集模块AABB 通讯协议

振弦采集模块AABB 通讯协议 AABB 通讯协议是一种非标准自定义协议&#xff0c; 相较于 MODBUS 通讯协议&#xff0c;结构更简单&#xff0c;指令生成方法更容易&#xff0c;便于进行快速测试。 AABB 通讯协议支持单寄存器读写两种指令。 &#xff08; 1&#xff09; 读取单个寄…

《Care Bears 爱心熊》人物化身来到 The Sandbox 元宇宙!

无论你想要快乐、和谐、幸运还是温暖&#xff0c;都会有一个适合你的爱心熊人物化身&#xff01;&#x1f43b; 想成为一只爱心熊吗&#xff1f; 《爱心熊》作品集是由 3060 个独特的 The Sandbox 人物化身组成的作品集&#xff0c;可在欢快而多彩的元宇宙世界中玩耍。每个人物…

【Linux】软件包管理器yum和编辑器vim(内附动图)

大家好我是沐曦希&#x1f495; 文章目录1.Linux 软件包管理器 yum1.1 什么是软件包1.2 第一个软件rzsz2.Linux编辑器-vim使用2.1 vim的基本概念2.2 vim的基本操作2.3 命令模式2.3.1 光标定位2.3.2 文本复制2.4 插入模式2.5 底行模式2.5.1 调用和取消行号2.5.2 底行&#xff01…

Node.js | 详解 Cookie-Session登录验证 的工作原理

&#x1f9d1;‍&#x1f4bc; 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; &#x1f5a5;️ 本系列专栏&#xff1a;Node.js从入门到精通 &#x1f449; 你的一键三连是我更新的最大动力❤️&#xff01; &#x1f4e2; 欢迎私信博主加入前端交流群&#x1f339; …

Maven版本3.6.1环境配置安装

官网下载安装包配置maven环境变量配置本地仓库以及阿里云镜像官网下载安装包 下载maven安装包官网地址&#xff0c;解压即可使用&#xff0c;推荐下载apache-maven-3.6.1-bin.zip 配置maven环境变量 找到此电脑右键-->点击属性-->选择高级系统设置-->点击环境变量--&g…