使用 Jenkins + 企微机器人 + docker + cypress + allure 完成自动化测试及结果通知

CI 镜像

镜像定义文件: ssoor/cypress:yk-test

FROM ubuntu:latest

RUN sed -i s@/archive.ubuntu.com/@/mirrors.tuna.tsinghua.edu.cn/@g /etc/apt/sources.list

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y curl && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install Node
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get update && \
    apt-get install -y nodejs && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install allure
RUN curl -sL https://hub.fastgit.xyz/allure-framework/allure2/releases/download/2.17.3/allure_2.17.3-1_all.deb -o /tmp/allure_2.deb  && \
    apt-get update && \
    apt-get install -y /tmp/allure_2.deb && \
    rm -f /tmp/allure_2.deb && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install cypress-dependencies
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
    libgtk2.0-0 \
    libgtk-3-0 \
    libgbm-dev \
    libnotify-dev \
    libgconf-2-4 \
    libnss3 \
    libxss1 \
    libasound2 \
    libxtst6 \
    xauth \
    xvfb && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install git
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y git && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install yarn
RUN npm config set registry 'https://registry.npm.taobao.org' && \
    npm install -g yarn --cache /tmp/empty-cache && \
    yarn config set registry 'https://registry.npm.taobao.org' && \
    rm -rf /tmp/empty-cache

RUN useradd -ms /bin/bash  app
USER app

# Configure npm global install path
RUN npm config set prefix '~/.npm-global' && \
    npm config set registry 'https://registry.npm.taobao.org' && \
    yarn config set registry 'https://registry.npm.taobao.org'
    
ENV PATH=~/.npm-global/bin:$PATH

# Install cypress
RUN npm install -g cypress

WORKDIR /app

开发镜像

开发使用的镜像定义文件:

FROM ssoor/cypress:yk-test

USER root

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
    git \
    curl \
    x11vnc \
    fluxbox && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

# Install noVNC
RUN git clone https://hub.fastgit.xyz/novnc/noVNC.git --depth 1 /usr/local/share/noVNC && \
    git clone https://hub.fastgit.xyz/novnc/websockify.git /usr/local/share/noVNC/utils/websockify && \
    ln -s /usr/local/share/noVNC/utils/novnc_proxy /usr/local/bin/novnc_proxy

# Install Chrome
RUN curl https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/google-chrome.deb && \
    apt-get update && \
    apt-get install -y /tmp/google-chrome.deb && \
    apt-get install ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy && \
    rm -f /tmp/google-chrome.deb && \
    apt-get clean all && rm -rf /var/lib/apt/lists/*

RUN npx cypress install

COPY start.sh /usr/local/bin/start.sh
COPY noVNC.html  /usr/local/share/noVNC/index.html

CMD ["/usr/local/bin/start.sh"]

镜像依赖文件

启动脚本:start.sh

#!/bin/bash

LANG=C.UTF-8
SCREEN_WHD="${SCREEN_WHD:-1440x900x16}"


Xvfb :20 -screen 0 "${SCREEN_WHD}" &
sleep 1
x11vnc -display :20 -forever -bg -o "/tmp/x11vnc.log"
sleep 1
DISPLAY=:20 fluxbox -log /tmp/fluxbox.log &
sleep 1
novnc_proxy --vnc localhost:5900 --listen 0.0.0.0:6080 --cert /app/ssl/root.crt  --key /app/ssl/root.key &
sleep 1

yarn
DISPLAY=:20 yarn cypress open --browser chrome

# yarn cypress run --env allure=true,allureResultsPath=results/allure -s cypress/integration/todo.spec.js
# allure serve -h 0.0.0.0 -p 1806 ./results/allure
wait

修改过的 noVNC,可选 - 可以使用官方版本。

<!DOCTYPE html>
<html lang="en" class="noVNC_loading">

<head>

    <!--
    noVNC example: simple example using default UI
    Copyright (C) 2019 The noVNC Authors
    noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
    This file is licensed under the 2-Clause BSD license (see LICENSE.txt).

    Connect parameters are provided in query string:
        http://example.com/?host=HOST&port=PORT&encrypt=1
    or the fragment:
        http://example.com/#host=HOST&port=PORT&encrypt=1
    -->
    <title>noVNC</title>

    <meta charset="utf-8">

    <!-- Icons (see app/images/icons/Makefile for what the sizes are for) -->
    <link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
    <link rel="icon" sizes="24x24" type="image/png" href="app/images/icons/novnc-24x24.png">
    <link rel="icon" sizes="32x32" type="image/png" href="app/images/icons/novnc-32x32.png">
    <link rel="icon" sizes="48x48" type="image/png" href="app/images/icons/novnc-48x48.png">
    <link rel="icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
    <link rel="icon" sizes="64x64" type="image/png" href="app/images/icons/novnc-64x64.png">
    <link rel="icon" sizes="72x72" type="image/png" href="app/images/icons/novnc-72x72.png">
    <link rel="icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
    <link rel="icon" sizes="96x96" type="image/png" href="app/images/icons/novnc-96x96.png">
    <link rel="icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
    <link rel="icon" sizes="144x144" type="image/png" href="app/images/icons/novnc-144x144.png">
    <link rel="icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
    <link rel="icon" sizes="192x192" type="image/png" href="app/images/icons/novnc-192x192.png">
    <!-- Firefox currently mishandles SVG, see #1419039
    <link rel="icon" sizes="any" type="image/svg+xml" href="app/images/icons/novnc-icon.svg">
    -->
    <!-- Repeated last so that legacy handling will pick this -->
    <link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">

    <!-- Apple iOS Safari settings -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Home Screen Icons (favourites and bookmarks use the normal icons) -->
    <link rel="apple-touch-icon" sizes="60x60" type="image/png" href="app/images/icons/novnc-60x60.png">
    <link rel="apple-touch-icon" sizes="76x76" type="image/png" href="app/images/icons/novnc-76x76.png">
    <link rel="apple-touch-icon" sizes="120x120" type="image/png" href="app/images/icons/novnc-120x120.png">
    <link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">

    <!-- Stylesheets -->
    <link rel="stylesheet" href="app/styles/base.css">

    <!-- Images that will later appear via CSS -->
    <link rel="preload" as="image" href="app/images/info.svg">
    <link rel="preload" as="image" href="app/images/error.svg">
    <link rel="preload" as="image" href="app/images/warning.svg">

    <script type="module" crossorigin="anonymous" src="app/error-handler.js"></script>
    <script type="module" crossorigin="anonymous" src="app/ui.js"></script>
    <script type="module">
        let init = false;
        let parentClipboard = "";
        const clipboardBtn = document.getElementById("noVNC_clipboard_button");
        const elementStyle = (elem) => elem.currentStyle ? elem.currentStyle : window.getComputedStyle(elem, null);

        const syncClipboard = () => {
            try {
                if (elementStyle(clipboardBtn).display == "none" || document.hasFocus() == false) {
                    return;
                }

                navigator.clipboard.readText().then(
                    (text) => {
                        text = text.replace(/\r\n/g,"\n");
                        const remoteClipboard = document.getElementById("noVNC_clipboard_text").value.replace(/\r\n/g,"\n");

                        if (init === false && text === remoteClipboard && remoteClipboard === "") {
                            init = true;
                            console.log("clipboard init");
                            document.getElementById("noVNC_clipboard_text").value = " ";
                            document.getElementById("noVNC_clipboard_text").dispatchEvent(new UIEvent('change'));
                            document.getElementById("noVNC_clipboard_text").value = "";
                            document.getElementById("noVNC_clipboard_text").dispatchEvent(new UIEvent('change'));
                        }


                        let sync = "";
                        if (parentClipboard !== text) {
                            sync = "local";
                        } else if (remoteClipboard !== text) {
                            sync = "remote";
                            text = remoteClipboard;
                        }

                        if (sync != "") {
                            init = true;
                            console.log(sync, "clipboard:", JSON.stringify(text));
                            parentClipboard = text;
                            navigator.clipboard.writeText(text);
                            document.getElementById("noVNC_clipboard_text").value = text;
                            document.getElementById("noVNC_clipboard_text").dispatchEvent(new UIEvent('change'));
                        }
                    }
                );
            } catch (e) {
            }
        }



        setInterval(syncClipboard, 200);
        setTimeout(() => { document.getElementById("noVNC_connect_button").dispatchEvent(new UIEvent('click')); }, 1000);
    </script>
</head>

<body>

    <div id="noVNC_fallback_error" class="noVNC_center">
        <div>
            <div>noVNC encountered an error:</div>
            <br>
            <div id="noVNC_fallback_errormsg"></div>
        </div>
    </div>

    <!-- noVNC Control Bar -->
    <div id="noVNC_control_bar_anchor" class="noVNC_vcenter">

        <div id="noVNC_control_bar">
            <div id="noVNC_control_bar_handle" title="Hide/Show the control bar">
                <div></div>
            </div>

            <div class="noVNC_scroll">

                <h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>

                <!-- Drag/Pan the viewport -->
                <input type="image" alt="Drag" src="app/images/drag.svg" id="noVNC_view_drag_button"
                    class="noVNC_button noVNC_hidden" title="Move/Drag Viewport">

                <!--noVNC Touch Device only buttons-->
                <div id="noVNC_mobile_buttons">
                    <input type="image" alt="Keyboard" src="app/images/keyboard.svg" id="noVNC_keyboard_button"
                        class="noVNC_button" title="Show Keyboard">
                </div>

                <!-- Extra manual keys -->
                <input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
                    id="noVNC_toggle_extra_keys_button" class="noVNC_button" title="Show Extra Keys">
                <div class="noVNC_vcenter">
                    <div id="noVNC_modifiers" class="noVNC_panel">
                        <input type="image" alt="Ctrl" src="app/images/ctrl.svg" id="noVNC_toggle_ctrl_button"
                            class="noVNC_button" title="Toggle Ctrl">
                        <input type="image" alt="Alt" src="app/images/alt.svg" id="noVNC_toggle_alt_button"
                            class="noVNC_button" title="Toggle Alt">
                        <input type="image" alt="Windows" src="app/images/windows.svg" id="noVNC_toggle_windows_button"
                            class="noVNC_button" title="Toggle Windows">
                        <input type="image" alt="Tab" src="app/images/tab.svg" id="noVNC_send_tab_button"
                            class="noVNC_button" title="Send Tab">
                        <input type="image" alt="Esc" src="app/images/esc.svg" id="noVNC_send_esc_button"
                            class="noVNC_button" title="Send Escape">
                        <input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
                            id="noVNC_send_ctrl_alt_del_button" class="noVNC_button" title="Send Ctrl-Alt-Del">
                    </div>
                </div>

                <!-- Shutdown/Reboot -->
                <input type="image" alt="Shutdown/Reboot" src="app/images/power.svg" id="noVNC_power_button"
                    class="noVNC_button" title="Shutdown/Reboot...">
                <div class="noVNC_vcenter">
                    <div id="noVNC_power" class="noVNC_panel">
                        <div class="noVNC_heading">
                            <img alt="" src="app/images/power.svg"> Power
                        </div>
                        <input type="button" id="noVNC_shutdown_button" value="Shutdown">
                        <input type="button" id="noVNC_reboot_button" value="Reboot">
                        <input type="button" id="noVNC_reset_button" value="Reset">
                    </div>
                </div>

                <!-- Clipboard -->
                <input type="image" alt="Clipboard" src="app/images/clipboard.svg" id="noVNC_clipboard_button"
                    class="noVNC_button" title="Clipboard">
                <div class="noVNC_vcenter">
                    <div id="noVNC_clipboard" class="noVNC_panel">
                        <div class="noVNC_heading">
                            <img alt="" src="app/images/clipboard.svg"> Clipboard
                        </div>
                        <textarea id="noVNC_clipboard_text" rows=5></textarea>
                        <br>
                        <input id="noVNC_clipboard_clear_button" type="button" value="Clear" class="noVNC_submit">
                    </div>
                </div>

                <!-- Toggle fullscreen -->
                <input type="image" alt="Full Screen" src="app/images/fullscreen.svg" id="noVNC_fullscreen_button"
                    class="noVNC_button noVNC_hidden" title="Full Screen">

                <!-- Settings -->
                <input type="image" alt="Settings" src="app/images/settings.svg" id="noVNC_settings_button"
                    class="noVNC_button" title="Settings">
                <div class="noVNC_vcenter">
                    <div id="noVNC_settings" class="noVNC_panel">
                        <ul>
                            <li class="noVNC_heading">
                                <img alt="" src="app/images/settings.svg"> Settings
                            </li>
                            <li>
                                <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
                            </li>
                            <li>
                                <label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label>
                            </li>
                            <li>
                                <hr>
                            </li>
                            <li>
                                <label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
                            </li>
                            <li>
                                <label for="noVNC_setting_resize">Scaling Mode:</label>
                                <select id="noVNC_setting_resize" name="vncResize">
                                    <option value="off">None</option>
                                    <option value="scale">Local Scaling</option>
                                    <option value="remote">Remote Resizing</option>
                                </select>
                            </li>
                            <li>
                                <hr>
                            </li>
                            <li>
                                <div class="noVNC_expander">Advanced</div>
                                <div>
                                    <ul>
                                        <li>
                                            <label for="noVNC_setting_quality">Quality:</label>
                                            <input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
                                        </li>
                                        <li>
                                            <label for="noVNC_setting_compression">Compression level:</label>
                                            <input id="noVNC_setting_compression" type="range" min="0" max="9"
                                                value="2">
                                        </li>
                                        <li>
                                            <hr>
                                        </li>
                                        <li>
                                            <label for="noVNC_setting_repeaterID">Repeater ID:</label>
                                            <input id="noVNC_setting_repeaterID" type="text" value="">
                                        </li>
                                        <li>
                                            <div class="noVNC_expander">WebSocket</div>
                                            <div>
                                                <ul>
                                                    <li>
                                                        <label><input id="noVNC_setting_encrypt" type="checkbox">
                                                            Encrypt</label>
                                                    </li>
                                                    <li>
                                                        <label for="noVNC_setting_host">Host:</label>
                                                        <input id="noVNC_setting_host">
                                                    </li>
                                                    <li>
                                                        <label for="noVNC_setting_port">Port:</label>
                                                        <input id="noVNC_setting_port" type="number">
                                                    </li>
                                                    <li>
                                                        <label for="noVNC_setting_path">Path:</label>
                                                        <input id="noVNC_setting_path" type="text" value="websockify">
                                                    </li>
                                                </ul>
                                            </div>
                                        </li>
                                        <li>
                                            <hr>
                                        </li>
                                        <li>
                                            <label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic
                                                Reconnect</label>
                                        </li>
                                        <li>
                                            <label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
                                            <input id="noVNC_setting_reconnect_delay" type="number">
                                        </li>
                                        <li>
                                            <hr>
                                        </li>
                                        <li>
                                            <label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No
                                                Cursor</label>
                                        </li>
                                        <li>
                                            <hr>
                                        </li>
                                        <!-- Logging selection dropdown -->
                                        <li>
                                            <label>Logging:
                                                <select id="noVNC_setting_logging" name="vncLogging">
                                                </select>
                                            </label>
                                        </li>
                                    </ul>
                                </div>
                            </li>
                            <li class="noVNC_version_separator">
                                <hr>
                            </li>
                            <li class="noVNC_version_wrapper">
                                <span>Version:</span>
                                <span class="noVNC_version"></span>
                            </li>
                        </ul>
                    </div>
                </div>

                <!-- Connection Controls -->
                <input type="image" alt="Disconnect" src="app/images/disconnect.svg" id="noVNC_disconnect_button"
                    class="noVNC_button" title="Disconnect">

            </div>
        </div>

        <div id="noVNC_control_bar_hint"></div>

    </div> <!-- End of noVNC_control_bar -->

    <!-- Status Dialog -->
    <div id="noVNC_status"></div>

    <!-- Connect button -->
    <div class="noVNC_center">
        <div id="noVNC_connect_dlg">
            <div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
            <div id="noVNC_connect_button">
                <div>
                    <img alt="" src="app/images/connect.svg"> Connect
                </div>
            </div>
        </div>
    </div>

    <!-- Server Key Verification Dialog -->
    <div class="noVNC_center noVNC_connect_layer">
        <div id="noVNC_verify_server_dlg" class="noVNC_panel">
            <form>
                <div class="noVNC_heading">
                    Server identity
                </div>
                <div>
                    The server has provided the following identifying information:
                </div>
                <div id="noVNC_fingerprint_block">
                    <b>Fingerprint:</b>
                    <span id="noVNC_fingerprint"></span>
                </div>
                <div>
                    Please verify that the information is correct and press
                    "Approve". Otherwise press "Reject".
                </div>
                <div>
                    <input id="noVNC_approve_server_button" type="submit" value="Approve" class="noVNC_submit">
                    <input id="noVNC_reject_server_button" type="button" value="Reject" class="noVNC_submit">
                </div>
            </form>
        </div>
    </div>

    <!-- Password Dialog -->
    <div class="noVNC_center noVNC_connect_layer">
        <div id="noVNC_credentials_dlg" class="noVNC_panel">
            <form>
                <div class="noVNC_heading">
                    Credentials
                </div>
                <div id="noVNC_username_block">
                    <label for="noVNC_username_input">Username:</label>
                    <input id="noVNC_username_input">
                </div>
                <div id="noVNC_password_block">
                    <label for="noVNC_password_input">Password:</label>
                    <input id="noVNC_password_input" type="password">
                </div>
                <div>
                    <input id="noVNC_credentials_button" type="submit" value="Send Credentials" class="noVNC_submit">
                </div>
            </form>
        </div>
    </div>

    <!-- Transition Screens -->
    <div id="noVNC_transition">
        <div id="noVNC_transition_text"></div>
        <div>
            <input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit">
        </div>
        <div class="noVNC_spinner"></div>
    </div>

    <!-- This is where the RFB elements will attach -->
    <div id="noVNC_container">
        <!-- Note that Google Chrome on Android doesn't respect any of these,
             html attributes which attempt to disable text suggestions on the
             on-screen keyboard. Let's hope Chrome implements the ime-mode
             style for example -->
        <textarea id="noVNC_keyboardinput" autocapitalize="off" autocomplete="off" spellcheck="false"
            tabindex="-1"></textarea>
    </div>

    <audio id="noVNC_bell">
        <source src="app/sounds/bell.oga" type="audio/ogg">
        <source src="app/sounds/bell.mp3" type="audio/mpeg">
    </audio>
</body>

</html>

Jenkinsfile 参考脚本

pipeline{
    agent any
    options {
        ansiColor('xterm')
    }
    stages{
        stage("执行测试用例"){
            agent {
                docker { image 'ssoor:cypress' }
            }
            steps{
                checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: '02007fe4-2bff-4989-98a1-1503397b03ea', url: 'https://github.com/ssoor/allure-report.git']]])
                dir("${CI_PROJECT_PATH}") {
                    echo "Install cypress dependency"
                    sh """
                        yarn install --production
                    """

                    echo "Generate cypress results"
                    sh """
                        rm -rf "results/allure"
                        npx cypress run -s cypress/integration/judge.spec.js
                    """
                }
                
                withCredentials([gitUsernamePassword(credentialsId: '02007fe4-2bff-4989-98a1-1503397b03ea', gitToolName: 'Default')]) {
                    sh 'git checkout origin/master'
                }  

                dir("${CI_PROJECT_PATH}") {
                    echo "Generate allure-report results from cypress"
                    sh """
                        mkdir -p "reports/allure/history"
                        cp -r "reports/allure/history" "results/allure"
                        allure generate "results/allure" -o "results/allure-report" --clean
                    """
                }
            }
        }
        stage("保存测试报告"){
            agent {
                docker { image 'ssoor:gitlab-runner' }
            }
            steps{
                dir("${CI_PROJECT_PATH}") {
                    // Jenkins 如果设置 Jenkinsfile 通过 GIT 仓库拉取
                    // 则每个 stage 都会触发 fetch 操作导致之前 stage 对仓库已有文件的修改丢失
                    // 所以在这里才真正修改仓库已有文件
                    echo "Save allure-report to git reports"
                    sh """
                        rm -rf "reports/allure"
                        mv "results/allure-report" "reports/allure"
                    """

                    echo "Commit allure-report to gitlab"
                    withCredentials([gitUsernamePassword(credentialsId: '02007fe4-2bff-4989-98a1-1503397b03ea', gitToolName: 'Default')]) {
                        sh """
                            git config --global user.name "gitlab-ci"
                            git config --global user.email "gitlab-ci@mail.com"
                        """
                        
                        sh """
                            git add .
                            git commit -m "Gitlab generate by ${BUILD_ID}"
                            git fetch origin master
                            git rebase origin/master 
                            git push -u origin HEAD:master
                        """
                    }
                }
            }
        }
        stage("发送测试结果通知"){
            agent {
                docker { image 'ssoor:gitlab-runner' }
            }
            environment {
                QYWX_ROBOT_URL = "${QYWX_ROBOT_URL}"
                CI_PROJECT_PATH = "${CI_PROJECT_PATH}"
                CI_COMMIT_BRANCH = "${CI_COMMIT_BRANCH}"
            }
            steps{
                dir("${CI_PROJECT_PATH}") {
                    echo "Send test repost to QYWX"
                    sh '''
                        RESULT_ALL=`cat reports/allure/history/history-trend.json | jq .[0].data`
                        RESULT_TOTAL=`echo $RESULT_ALL | jq .total`
                        RESULT_PASSED=`echo $RESULT_ALL | jq .passed`
                        RESULT_FAILED=`echo $RESULT_ALL | jq .failed`
                        RESULT_SKIPPED=`echo $RESULT_ALL | jq .skipped`
                        cat | bash << EOF
                        curl --location --request POST '${QYWX_ROBOT_URL}' \
                        --header 'Content-Type: application/json' \
                        --data-raw '{
                            "msgtype": "markdown",
                            "markdown": {
                            "content": "# 仓库:*<font color=\\"#660000\\">[${CI_PROJECT_PATH}](https://github.com/${CI_PROJECT_PATH})</font>*\\n\\n\\n\\n本次执行用例 ${RESULT_TOTAL} 例,执行分支:<font color=\\"#000066\\">**${CI_COMMIT_BRANCH}**</font>\\n> 成功:<font color=\\"#006600\\">${RESULT_PASSED}例</font>\\n> 失败:<font color=\\"#dd0000\\">${RESULT_FAILED}例</font>\\n> 跳过:<font color=\\"#808080\\">${RESULT_SKIPPED}例</font>\\n\\n点击查看详情:[Allure-report](http://10.9.40.75:4480/${CI_PROJECT_PATH})"
                            }
                        }'
                    '''
                }
            }
        }
    }
}

cypress.json 配置文件

{
    "defaultCommandTimeout": 0,
    "env": {
        "allure": true,
        "allureAttachRequests": true,
        "allureResultsPath": "./results/allure",
        "JUDGE_ORGCODE": "huaxiaadmin_test",
        "JUDGE_USERCODE": "mysoftadmin",
        "JUDGE_URL": "http://gateway-test.myscrm.cn/channel-judge/v1/judge"
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值