В скрипте groovy в результатах теста Дженкинса, как мы можем получить информацию о пропущенных тестах, чтобы показать, был ли тест ожидаемым: провал (успешно или неудачно) или пропущен? - PullRequest
0 голосов
/ 07 января 2020

Результат теста Дженкинса GUI показывает пропущенные или ожидаемые ошибки теста как пропущенные. Отдельное представление теста для пропущенных или ожидаемых тестов с ошибками показывает «Пропущенное сообщение» и «Стандартный вывод»

, например, «Пропущенное сообщение» может быть:

  • пользовательское сообщение пропуска

        *  e.g. from python @unittest.skip("some reason") tag or 
        *  e.g. raise unittest.SkipTest("thing not found.")
    
  • "ожидаемый сбой теста"
  • "тест с пометкой xfail неожиданно прошел"

Мы используем скрипт groovy для генерировать отчеты о тестировании. Мы хотели бы включить больше информации о пропущенных тестах, а не просто "пропущенных". Как мы можем получить информацию о пропущенном тесте, как в «Пропущенном сообщении» в представлении GUI?

API jenkins задокументирован здесь:

https://javadoc.jenkins.io/plugin/junit/hudson/tasks/junit/TestResult.html

Нет специального вызова c для получения информации о пропущенных или ожидаемых неудачных тестах. Я надеюсь, что после некоторых экспериментов можно будет получить информацию об ожидаемой ошибке через этот API-интерфейс testResult. Начиная с этих вызовов API:

String  getErrorDetails()
If there was an error or a failure, this is the text from the message.

String  getErrorStackTrace()
If there was an error or a failure, this is the stack trace, or otherwise null.

String  getName()
Gets the name of this object.

String  getStderr()
The stderr of this test.

String  getStdout()
The stdout of this test.

TestResult  getTestResult()
Returns the top level test result data.

String  getTitle()
Gets the human readable title of this result object.

В GUI:

  • Обычный пройденный тест просто имеет "Стандартный вывод".
  • Нормальный сбой В тесте есть «Сообщение об ошибке» и «Stacktrace» и «Стандартный вывод».
  • Пропущенный или ожидаемый сбой тестов показывает «Пропущенное сообщение» и «Стандартный вывод».

Мы используем python unittest, выводящий файлы результатов теста junit. Загрузка этого в jenkins с помощью плагина результатов теста junit.

Я что-то пропустил в API-интерфейсе результатов теста jenkins, который предоставил бы дополнительную информацию об ожидаемых неудачных или пропущенных тестах? Я надеюсь найти информацию путем экспериментов с использованием API. И задокументируйте это в ответе здесь.

Вот сценарий отчета о тестировании groovy скрипт (используется в jenkins Execute Groovy Плагин скрипта после того, как плагин результата jUnit собрал результаты теста):

import hudson.model.*
def build = Thread.currentThread().executable
workspace = build.getEnvVars()["WORKSPACE"]
reportfilename = workspace + "/testreport.html"
rf = new File(reportfilename);


def testCount = "0"
def testPassed = "0"
def testFailed = "0"
def testSkipped = "0"
def buildDuration = "0"

def workspace = "unknown"
def buildName = "unknown"
def BUILD_STATUS = ""
def BUILD_URL = ""

def testResult = null
def testResult1 = null
def testResult2 = null
def testDuration = ""
def caseResult = null

def buildNumber = 0
def buildNumHash = ""
def buildTimeString = ""
def rooturl = ""

try {
    buildNumber = build.number
    buildNumHash = build.getDisplayName()
    //currentBuildNumber = manager.build.number

    buildTimeString = build.getTime().format("YYYY-MMM-dd HH:mm:ss")

    if(build.testResultAction) {
        testResult = build.testResultAction
        testCount = String.format("%d",(testResult.totalCount))
        testPassed = String.format("%d",(testResult.result.passCount))
        testFailed = String.format("%d",(testResult.result.failCount))
        testSkipped = String.format("%d",(testResult.result.skipCount))
        testDuration = String.format("%.2f",(testResult.result.duration ))
    }

    workspace = build.getEnvVars()["WORKSPACE"]
    buildName = build.getEnvVars()["JOB_NAME"]
    BUILD_STATUS = build.getEnvVars()["BUILD_STATUS"]
    BUILD_URL = build.getEnvVars()["BUILD_URL"]

    testResult1 = hudson.tasks.junit.TestResult 
    testResult2 = build.getAction(hudson.tasks.junit.TestResultAction.class)
    caseResult = hudson.tasks.junit.CaseResult

    rooturl = manager.hudson.rootUrl

} catch(Exception ex) {
    rf << "exception accessing build.testResultAction object.";
    //rf << ex;
}

// in groovy the write RE-creates the file, rf << "whatever" is used to append.
rf.write "<html><head><title>testreport.groovy #$buildNumber $buildName</title></head><body>"

rf << "Summary test report <br><br>\n\
<b>TEST RESULT:</b> $testCount total, <b>$testPassed pass</b>, <b>$testFailed fail</b>, $testSkipped skip.<br>\n\
Workspace : $workspace<br>\n\
Project Name : $buildName $buildNumHash<br><br>\n\
"

if (build) {

    rf << """<!-- GENERAL INFO -->\n\
\n\
<TABLE>\n\
  <TR><TD align=\"right\">\n\
    <j:choose>\n\
      <j:when test=\"${build.result=='SUCCESS'}\">\n\
        <IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/blue.gif\" />\n\
      </j:when>\n\
      <j:when test=\"${build.result=='FAILURE'}\">\n\
        <IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/red.gif\" />\n\
      </j:when>\n\
      <j:otherwise>\n\
        <IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/yellow.gif\" />\n\
      </j:otherwise>\n\
    </j:choose>\n\
  </TD><TD valign='center'><B style='font-size: 200%;'>BUILD ${build.result}</B></TD></TR>\n\
  <TR><TD>Build URL</TD><TD><A href=\"${rooturl}${build.url}\">${rooturl}${build.url}</A></TD></TR>\n\
  <TR><TD>Project:</TD><TD>${buildName}</TD></TR>\n\
  <TR><TD>Date of build:</TD><TD>${buildTimeString}</TD></TR>\n\
  <TR><TD>Build duration:</TD><TD>${build.durationString}</TD></TR>\n\
  <TR><TD>Test duration:</TD><TD>${testDuration}</TD></TR>\n\
</TABLE>\n\
<BR/>\n\
"""
}

if(!testResult) {
    rf << "<br>No test result<br>"
    rf << "</body></html>"
    return ("No test result")
}

def junitResultList = [];
junitResultList.add(testResult.getResult())
if (junitResultList.size() > 0) {
    rf << "<br>test result from build.testResultAction"
} else {
    junitResultList.add(testResult2.getResult())
    if (junitResultList.size() > 0) {
        rf << "<br>test result from build.getAction"
    } else {
        rf << "<br>No results in 'testResult2'<br>\n"
        junitResultList.add(testResult1.getResult())
    }
}
//rf << "<br>DEBUG" + junitResultList.size() + " test items"
// API: http://hudson-ci.org/javadoc/hudson/tasks/junit/PackageResult.html

rf << "<!-- JUnit TEMPLATE: all tests PASS FAIL SKIP -->\n"
if (junitResultList.size() > 0) { 
    rf << '<TABLE width="100%">\n'
    rf << "<TR><TD class='bg1' colspan='2'><B>${junitResultList.first().displayName}</B></TD></TR>\n"
    junitResultList.each { junitResult -> 
        junitResult.getChildren().each { packageResult -> 
            rf << "<TR><TD class='bg2' colspan='2'> <B>TEST SUITE: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s)</B>, Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>\n"
            packageResult.getChildren().each { suite -> 
                suite.getChildren().each { test ->
                    def colour = "lightgreen"
                    def highlight1=""
                    def highlight2=""
                    RESULT = test.getStatus().name() // FAILED or PASSED or SKIPPED (.name() not .value)
                    // hudson.tasks.junit.CaseResult.Status.FAILED
                    if (RESULT == "FAILED" || RESULT == "REGRESSION") {
                        colour = "#ffcccc" 
                        highlight1="<B>"
                        highlight2="</B>"
                    }
                    if (RESULT == "SKIPPED") { colour = "#ffffb3" }

                    rf << "<TR bgcolor='${colour}'><TD class='test' colspan='2'>${highlight1}<li>${RESULT}: ${test.getFullName()} </li>${highlight2}</TD></TR>\n"
                } 
            }
        }
    } 
    rf << '</TABLE><BR/>\n'
}

rf << "testreport.groovy</body></html>\n"


1 Ответ

0 голосов
/ 09 января 2020

Я нашел это! Ответ - вызвать недокументированный метод test.getSkippedMessage (). Это видно в исходном коде.

py.test записывает пропущенное сообщение в junit xml. Отметьте как это внутри результата теста: <skipped message="the skipped message">

Это сообщение может быть пользовательским сообщением из сообщения в вызове skip (), или в случае xfail или xpass сообщение устанавливается pytest на «ожидаемый сбой теста» "или" отмеченный xfail тест прошел неожиданно ".

плагин jenkins junit считывает junit xml. Сообщение доступно через API здесь: класс CaseResult getSkippedMessage () см. https://github.com/jenkinsci/junit-plugin/blob/master/src/main/java/hudson/tasks/junit/CaseResult.java Хотя оно здесь не задокументировано: http://hudson-ci.org/javadoc/hudson/tasks/junit/CaseResult.html

Изменить эту часть код выше от:

                    if (RESULT == "SKIPPED") { colour = "#ffffb3" }

до:

                    def moremessage1 = "";

.
.
.

                    if (RESULT == "SKIPPED") { 
                        colour = "#ffffb3" 
                        moremessage1 += "<br>test.getSkippedMessage():" + test.getSkippedMessage() + "</br>"
                    }

                    rf << "<TR bgcolor='${colour}'><TD class='test' colspan='2'>${highlight1}<li>${RESULT}: ${test.getFullName()} ${moremessage1}</li>${highlight2}</TD></TR>\n"

больше тестового кода, полезного при экспериментировании с этим API:

                    if (RESULT == "SKIPPED") { 
                        colour = "#ffffb3" 
                        moremessage1 += "<br>test.getSkippedMessage():" + test.getSkippedMessage() + "</br>"
                        moremessage1 += "<br>test.getStatus().getMessage():" + test.getStatus().getMessage() + "</br>"
                        moremessage1 += "<br>test.getTitle():" + test.getTitle() + "</br>"
                        moremessage1 += "<br>test.getStdout():" + test.getStdout() + "</br>"
                        moremessage1 += "<br>test.getStderr():" + test.getStderr() + "</br>"
                        moremessage1 += "<br>test.getErrorDetails():" + test.getErrorDetails() + "</br>"
                        moremessage1 += "<br>test.getErrorStackTrace():" + test.getErrorStackTrace() + "</br>"
                        moremessage1 += "<br>test.getName():" + test.getName() + "</br>"
                        moremessage1 += "<br>test.getSafeName():" + test.getSafeName() + "</br>"
                        moremessage1 += "<br>test.getSimpleName():" + test.getSimpleName() + "</br>"
                        moremessage1 += "<br>test.getFullName():" + test.getFullName() + "</br>"
                        moremessage1 += "<br>test.getClassName():" + test.getClassName() + "</br>"
                        moremessage1 += "<br>test.getDisplayName():" + test.getDisplayName() + "</br>"
                        moremessage1 += "<br>test.getPackageName():" + test.getPackageName() + "</br>"
...