...

Source file src/github.com/onsi/ginkgo/v2/reporters/teamcity_report.go

Documentation: github.com/onsi/ginkgo/v2/reporters

     1  /*
     2  
     3  TeamCity Reporter for Ginkgo
     4  
     5  Makes use of TeamCity's support for Service Messages
     6  http://confluence.jetbrains.com/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingTests
     7  */
     8  
     9  package reporters
    10  
    11  import (
    12  	"fmt"
    13  	"os"
    14  	"path"
    15  	"strings"
    16  
    17  	"github.com/onsi/ginkgo/v2/types"
    18  )
    19  
    20  func tcEscape(s string) string {
    21  	s = strings.ReplaceAll(s, "|", "||")
    22  	s = strings.ReplaceAll(s, "'", "|'")
    23  	s = strings.ReplaceAll(s, "\n", "|n")
    24  	s = strings.ReplaceAll(s, "\r", "|r")
    25  	s = strings.ReplaceAll(s, "[", "|[")
    26  	s = strings.ReplaceAll(s, "]", "|]")
    27  	return s
    28  }
    29  
    30  func GenerateTeamcityReport(report types.Report, dst string) error {
    31  	if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
    32  		return err
    33  	}
    34  	f, err := os.Create(dst)
    35  	if err != nil {
    36  		return err
    37  	}
    38  
    39  	name := report.SuiteDescription
    40  	labels := report.SuiteLabels
    41  	if len(labels) > 0 {
    42  		name = name + " [" + strings.Join(labels, ", ") + "]"
    43  	}
    44  	fmt.Fprintf(f, "##teamcity[testSuiteStarted name='%s']\n", tcEscape(name))
    45  	for _, spec := range report.SpecReports {
    46  		name := fmt.Sprintf("[%s]", spec.LeafNodeType)
    47  		if spec.FullText() != "" {
    48  			name = name + " " + spec.FullText()
    49  		}
    50  		labels := spec.Labels()
    51  		if len(labels) > 0 {
    52  			name = name + " [" + strings.Join(labels, ", ") + "]"
    53  		}
    54  
    55  		name = tcEscape(name)
    56  		fmt.Fprintf(f, "##teamcity[testStarted name='%s']\n", name)
    57  		switch spec.State {
    58  		case types.SpecStatePending:
    59  			fmt.Fprintf(f, "##teamcity[testIgnored name='%s' message='pending']\n", name)
    60  		case types.SpecStateSkipped:
    61  			message := "skipped"
    62  			if spec.Failure.Message != "" {
    63  				message += " - " + spec.Failure.Message
    64  			}
    65  			fmt.Fprintf(f, "##teamcity[testIgnored name='%s' message='%s']\n", name, tcEscape(message))
    66  		case types.SpecStateFailed:
    67  			details := failureDescriptionForUnstructuredReporters(spec)
    68  			fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='failed - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details))
    69  		case types.SpecStatePanicked:
    70  			details := failureDescriptionForUnstructuredReporters(spec)
    71  			fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='panicked - %s' details='%s']\n", name, tcEscape(spec.Failure.ForwardedPanic), tcEscape(details))
    72  		case types.SpecStateTimedout:
    73  			details := failureDescriptionForUnstructuredReporters(spec)
    74  			fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='timedout - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details))
    75  		case types.SpecStateInterrupted:
    76  			details := failureDescriptionForUnstructuredReporters(spec)
    77  			fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='interrupted - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details))
    78  		case types.SpecStateAborted:
    79  			details := failureDescriptionForUnstructuredReporters(spec)
    80  			fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='aborted - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details))
    81  		}
    82  
    83  		fmt.Fprintf(f, "##teamcity[testStdOut name='%s' out='%s']\n", name, tcEscape(systemOutForUnstructuredReporters(spec)))
    84  		fmt.Fprintf(f, "##teamcity[testStdErr name='%s' out='%s']\n", name, tcEscape(systemErrForUnstructuredReporters(spec)))
    85  		fmt.Fprintf(f, "##teamcity[testFinished name='%s' duration='%d']\n", name, int(spec.RunTime.Seconds()*1000.0))
    86  	}
    87  	fmt.Fprintf(f, "##teamcity[testSuiteFinished name='%s']\n", tcEscape(report.SuiteDescription))
    88  
    89  	return f.Close()
    90  }
    91  
    92  func MergeAndCleanupTeamcityReports(sources []string, dst string) ([]string, error) {
    93  	messages := []string{}
    94  	merged := []byte{}
    95  	for _, source := range sources {
    96  		data, err := os.ReadFile(source)
    97  		if err != nil {
    98  			messages = append(messages, fmt.Sprintf("Could not open %s:\n%s", source, err.Error()))
    99  			continue
   100  		}
   101  		os.Remove(source)
   102  		merged = append(merged, data...)
   103  	}
   104  	return messages, os.WriteFile(dst, merged, 0666)
   105  }
   106  

View as plain text