web-dev-qa-db-ja.com

Jenkins PipelineプロジェクトでJunitテストカウントにアクセスする方法

私はジェンキンスで始めたばかりです

このようなSlackでのJUnitテストの結果を報告するために使用した私のフリースタイルプロジェクト

MyJenkinsFreestyle - #79 Unstable after 4 min 59 sec (Open)
Test Status:
    Passed: 2482, Failed: 13, Skipped: 62

今、私は同じものをパイプラインプロジェクトに移動しましたが、Slack通知にテストステータスがないことを除いてすべてが良いです

done MyPipelineProject #68 UNSTABLE

Slackに送信するメッセージを作成する必要があることは理解していますが、今のところ上記の手順を実行しています。

唯一の問題は、テストステータスをどのように読み取るかです-合格したカウント、失敗したカウントなど。これは、Jenkins slack-plugin commit で「テストサマリー」と呼ばれ、スクリーンショット testsummaryimage

Jenkins PipelineプロジェクトでJunitテストのカウント/詳細にアクセスするにはどうすればよいですか? -これらが通知で報告されるように。

更新:Freestyleプロジェクトでは、Slack通知自体に「テストサマリー」があり、テストサマリーを選択する(またはしない)オプションはありません。

Pipelineプロジェクトでは、Slack通知を送信する前に「JUnitテスト結果を公開する」という「junit」コマンドを使用します。

したがって、コードでは、これらの行は次のようになります(これは最後のステージの最後の行です)。

bat runtests.bat
junit 'junitreport/xml/TEST*.xml'
slackSend channel: '#testschannel', color: 'normal', message: "done ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)";
17
vikramsjn

Cloudbeesの このプレゼンテーション から、「build」オブジェクトを介して可能になるはずであることがわかりました。次のようなコードがあります

def testResult = build.testResultAction
def total = testResult.totalCount

ただし、currentBuildはtestResultActionへのアクセスを提供しません。

検索を続け、この投稿を見つけました 「パイプラインスクリプトで失敗したテストに反応する」 。そこでロバート・サンデルは "pro tip" を与えました。

プロのヒント、いくつかの「カスタムホワイトリスト」が必要です。

AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
if (testResultAction != null) {
    echo "Tests: ${testResultAction.failCount} / ${testResultAction.failureDiffString} failures of ${testResultAction.totalCount}.\n\n" 
}

これは魅力的でした-「Groovy sandbox」チェックボックスの選択を解除しなければなりませんでした。今、私はビルドログにこれらを持っています

Tests: 11  / ±0 failures of 2624

次に、これを使用して、テスト結果をスラックに通知する文字列を準備します。


更新:

最後に、次のような出力を取得するために使用した関数(テストが失敗した後の「failure diff」に注意してください)

Test Status:
  Passed: 2628, Failed: 6  / ±0, Skipped: 0

以下は:

import hudson.tasks.test.AbstractTestResultAction

@NonCPS
def testStatuses() {
    def testStatus = ""
    AbstractTestResultAction testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
    if (testResultAction != null) {
        def total = testResultAction.totalCount
        def failed = testResultAction.failCount
        def skipped = testResultAction.skipCount
        def passed = total - failed - skipped
        testStatus = "Test Status:\n  Passed: ${passed}, Failed: ${failed} ${testResultAction.failureDiffString}, Skipped: ${skipped}"

        if (failed == 0) {
            currentBuild.result = 'SUCCESS'
        }
    }
    return testStatus
}

2018-04-19更新

上記では、使用する方法の手動の「ホワイトリスト」が必要であることに注意してください。すべてのメソッドを一度にホワイトリストに登録する方法を次に示します

ホワイトリストを手動で更新...

ジェンキンスを出る

次の内容で%USERPROFILE%.jenkins\scriptApproval.xmlを作成/更新します

<?xml version='1.0' encoding='UTF-8'?>
<scriptApproval plugin="[email protected]">
<approvedScriptHashes>
</approvedScriptHashes>
<approvedSignatures>
<string>method hudson.model.Actionable getAction Java.lang.Class</string>
<string>method hudson.model.Cause getShortDescription</string>
<string>method hudson.model.Run getCauses</string>
<string>method hudson.tasks.test.AbstractTestResultAction getFailCount</string>
<string>method hudson.tasks.test.AbstractTestResultAction getFailureDiffString</string>
<string>method hudson.tasks.test.AbstractTestResultAction getSkipCount</string>
<string>method hudson.tasks.test.AbstractTestResultAction getTotalCount</string>
<string>method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild</string>
</approvedSignatures>
<aclApprovedSignatures/>
<approvedClasspathEntries/>
<pendingScripts/>
<pendingSignatures/>
<pendingClasspathEntries/>
</scriptApproval>
  • Jenkinsを再起動します
  • 次に、「スクリプトの承認」で上記のエントリが承認されていることを確認します
  • 注:それは重要です。そのため、scriptApprovalファイルが既に存在する場合、通常はタグの内容を確認する必要があります。
30
vikramsjn

@vikramsjnの答えを拡張するために、ここにJenkinsfileでテストの要約を取得するために使用するものを示します。

import hudson.tasks.test.AbstractTestResultAction
import hudson.model.Actionable

@NonCPS
def getTestSummary = { ->
    def testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
    def summary = ""

    if (testResultAction != null) {
        def total = testResultAction.getTotalCount()
        def failed = testResultAction.getFailCount()
        def skipped = testResultAction.getSkipCount()

        summary = "Test results:\n\t"
        summary = summary + ("Passed: " + (total - failed - skipped))
        summary = summary + (", Failed: " + failed)
        summary = summary + (", Skipped: " + skipped)
    } else {
        summary = "No tests found"
    }
    return summary
}

次に、このメソッドを使用してtestSummary変数をインスタンス化します。

def testSummary = getTestSummary()

次のような結果が返されます。

"Test results:
     Passed: 123, Failed: 0, Skipped: 0"
8

まず、上記の回答をありがとうございます。彼らは私に多くの時間を節約し、パイプラインで提案されたソリューションを使用しました。ただし、「ホワイトリスト」を使用しなかったため、正常に機能します。私はJenkinsパイプラインに共有ライブラリを使用します。ここに、パイプラインとカウントを取得するメソッドを使用した共有ライブラリの一部を示します。

import hudson.model.*
import jenkins.model.*
import hudson.tasks.test.AbstractTestResultAction

def call(Closure body) {
    ...

    def emailTestReport = ""

    pipeline {
        ...

        stages{
            stage('Test'){
                ...
                post {
                    always {
                        junit 'tests.xml'

                        script {
                            AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
                            if (testResultAction != null) {
                                def totalNumberOfTests = testResultAction.totalCount
                                def failedNumberOfTests = testResultAction.failCount
                                def failedDiff = testResultAction.failureDiffString
                                def skippedNumberOfTests = testResultAction.skipCount
                                def passedNumberOfTests = totalNumberOfTests - failedNumberOfTests - skippedNumberOfTests
                                emailTestReport = "Tests Report:\n Passed: ${passedNumberOfTests}; Failed: ${failedNumberOfTests} ${failedDiff}; Skipped: ${skippedNumberOfTests}  out of ${totalNumberOfTests} "
                            }
                        }

                        mail to: '[email protected]',
                        subject: "Tests are finished: ${currentBuild.fullDisplayName}",
                        body: "Tests are finished  ${env.BUILD_URL}\n  Test Report: ${emailTestReport} "
                    }

                }
            }
        }
    }
}

追伸スクリプト「セクション」内のローカル変数としてemailTestRepotを作成すると、次の例外が発生します。

an exception which occurred:
    in field locals
    in field parent
    in field caller
    in field e
    in field program
    in field threads
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@11cd92de
Caused: Java.io.NotSerializableException: hudson.tasks.junit.TestResultAction
...

私は、Java.io.NotSerializableExceptionを修正しようと多くの苦労をしました。理解したように、NotSerializableExceptionを防ぐために「ホワイトリスト」を使用する必要がありました。しかし、私は本当にそれをやりたくありませんでした。「def emailTestReport」をパイプラインから移動したとき、それはうまく機能しました。

1