...

Source file src/github.com/onsi/ginkgo/v2/reporting_dsl.go

Documentation: github.com/onsi/ginkgo/v2

     1  package ginkgo
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/onsi/ginkgo/v2/internal"
     8  	"github.com/onsi/ginkgo/v2/internal/global"
     9  	"github.com/onsi/ginkgo/v2/reporters"
    10  	"github.com/onsi/ginkgo/v2/types"
    11  )
    12  
    13  /*
    14  Report represents the report for a Suite.
    15  It is documented here: https://pkg.go.dev/github.com/onsi/ginkgo/v2/types#Report
    16  */
    17  type Report = types.Report
    18  
    19  /*
    20  Report represents the report for a Spec.
    21  It is documented here: https://pkg.go.dev/github.com/onsi/ginkgo/v2/types#SpecReport
    22  */
    23  type SpecReport = types.SpecReport
    24  
    25  /*
    26  CurrentSpecReport returns information about the current running spec.
    27  The returned object is a types.SpecReport which includes helper methods
    28  to make extracting information about the spec easier.
    29  
    30  You can learn more about SpecReport here: https://pkg.go.dev/github.com/onsi/ginkgo/types#SpecReport
    31  You can learn more about CurrentSpecReport() here: https://onsi.github.io/ginkgo/#getting-a-report-for-the-current-spec
    32  */
    33  func CurrentSpecReport() SpecReport {
    34  	return global.Suite.CurrentSpecReport()
    35  }
    36  
    37  /*
    38  	ReportEntryVisibility governs the visibility of ReportEntries in Ginkgo's console reporter
    39  
    40  - ReportEntryVisibilityAlways: the default behavior - the ReportEntry is always emitted.
    41  - ReportEntryVisibilityFailureOrVerbose: the ReportEntry is only emitted if the spec fails or if the tests are run with -v (similar to GinkgoWriters behavior).
    42  - ReportEntryVisibilityNever: the ReportEntry is never emitted though it appears in any generated machine-readable reports (e.g. by setting `--json-report`).
    43  
    44  You can learn more about Report Entries here: https://onsi.github.io/ginkgo/#attaching-data-to-reports
    45  */
    46  type ReportEntryVisibility = types.ReportEntryVisibility
    47  
    48  const ReportEntryVisibilityAlways, ReportEntryVisibilityFailureOrVerbose, ReportEntryVisibilityNever = types.ReportEntryVisibilityAlways, types.ReportEntryVisibilityFailureOrVerbose, types.ReportEntryVisibilityNever
    49  
    50  /*
    51  AddReportEntry generates and adds a new ReportEntry to the current spec's SpecReport.
    52  It can take any of the following arguments:
    53    - A single arbitrary object to attach as the Value of the ReportEntry.  This object will be included in any generated reports and will be emitted to the console when the report is emitted.
    54    - A ReportEntryVisibility enum to control the visibility of the ReportEntry
    55    - An Offset or CodeLocation decoration to control the reported location of the ReportEntry
    56  
    57  If the Value object implements `fmt.Stringer`, it's `String()` representation is used when emitting to the console.
    58  
    59  AddReportEntry() must be called within a Subject or Setup node - not in a Container node.
    60  
    61  You can learn more about Report Entries here: https://onsi.github.io/ginkgo/#attaching-data-to-reports
    62  */
    63  func AddReportEntry(name string, args ...interface{}) {
    64  	cl := types.NewCodeLocation(1)
    65  	reportEntry, err := internal.NewReportEntry(name, cl, args...)
    66  	if err != nil {
    67  		Fail(fmt.Sprintf("Failed to generate Report Entry:\n%s", err.Error()), 1)
    68  	}
    69  	err = global.Suite.AddReportEntry(reportEntry)
    70  	if err != nil {
    71  		Fail(fmt.Sprintf("Failed to add Report Entry:\n%s", err.Error()), 1)
    72  	}
    73  }
    74  
    75  /*
    76  ReportBeforeEach nodes are run for each spec, even if the spec is skipped or pending.  ReportBeforeEach nodes take a function that
    77  receives a SpecReport or both SpecContext and Report for interruptible behavior. They are called before the spec starts.
    78  
    79  Example:
    80  
    81  	ReportBeforeEach(func(report SpecReport) { // process report  })
    82  	ReportBeforeEach(func(ctx SpecContext, report SpecReport) {
    83  		// process report
    84  	}), NodeTimeout(1 * time.Minute))
    85  
    86  You cannot nest any other Ginkgo nodes within a ReportBeforeEach node's closure.
    87  You can learn more about ReportBeforeEach here: https://onsi.github.io/ginkgo/#generating-reports-programmatically
    88  
    89  You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spec-timeouts-and-interruptible-nodes
    90  */
    91  func ReportBeforeEach(body any, args ...any) bool {
    92  	combinedArgs := []interface{}{body}
    93  	combinedArgs = append(combinedArgs, args...)
    94  
    95  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportBeforeEach, "", combinedArgs...))
    96  }
    97  
    98  /*
    99  ReportAfterEach nodes are run for each spec, even if the spec is skipped or pending.
   100  ReportAfterEach nodes take a function that receives a SpecReport or both SpecContext and Report for interruptible behavior.
   101  They are called after the spec has completed and receive the final report for the spec.
   102  
   103  Example:
   104  
   105  	ReportAfterEach(func(report SpecReport) { // process report  })
   106  	ReportAfterEach(func(ctx SpecContext, report SpecReport) {
   107  		// process report
   108  	}), NodeTimeout(1 * time.Minute))
   109  
   110  You cannot nest any other Ginkgo nodes within a ReportAfterEach node's closure.
   111  You can learn more about ReportAfterEach here: https://onsi.github.io/ginkgo/#generating-reports-programmatically
   112  
   113  You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spec-timeouts-and-interruptible-nodes
   114  */
   115  func ReportAfterEach(body any, args ...any) bool {
   116  	combinedArgs := []interface{}{body}
   117  	combinedArgs = append(combinedArgs, args...)
   118  
   119  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportAfterEach, "", combinedArgs...))
   120  }
   121  
   122  /*
   123  ReportBeforeSuite nodes are run at the beginning of the suite.  ReportBeforeSuite nodes take a function
   124  that can either receive Report or both SpecContext and Report for interruptible behavior.
   125  
   126  Example Usage:
   127  
   128  	ReportBeforeSuite(func(r Report) { // process report })
   129  	ReportBeforeSuite(func(ctx SpecContext, r Report) {
   130  		// process report
   131  	}, NodeTimeout(1 * time.Minute))
   132  
   133  They are called at the beginning of the suite, before any specs have run and any BeforeSuite or SynchronizedBeforeSuite nodes, and are passed in the initial report for the suite.
   134  ReportBeforeSuite nodes must be created at the top-level (i.e. not nested in a Context/Describe/When node)
   135  
   136  # When running in parallel, Ginkgo ensures that only one of the parallel nodes runs the ReportBeforeSuite
   137  
   138  You cannot nest any other Ginkgo nodes within a ReportAfterSuite node's closure.
   139  You can learn more about ReportAfterSuite here: https://onsi.github.io/ginkgo/#generating-reports-programmatically
   140  
   141  You can learn more about Ginkgo's reporting infrastructure, including generating reports with the CLI here: https://onsi.github.io/ginkgo/#generating-machine-readable-reports
   142  
   143  You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spec-timeouts-and-interruptible-nodes
   144  */
   145  func ReportBeforeSuite(body any, args ...any) bool {
   146  	combinedArgs := []interface{}{body}
   147  	combinedArgs = append(combinedArgs, args...)
   148  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportBeforeSuite, "", combinedArgs...))
   149  }
   150  
   151  /*
   152  ReportAfterSuite nodes are run at the end of the suite. ReportAfterSuite nodes execute at the suite's conclusion,
   153  and accept a function that can either receive Report or both SpecContext and Report for interruptible behavior.
   154  
   155  Example Usage:
   156  
   157  	ReportAfterSuite("Non-interruptible ReportAfterSuite", func(r Report) { // process report })
   158  	ReportAfterSuite("Interruptible ReportAfterSuite", func(ctx SpecContext, r Report) {
   159  		// process report
   160  	}, NodeTimeout(1 * time.Minute))
   161  
   162  They are called at the end of the suite, after all specs have run and any AfterSuite or SynchronizedAfterSuite nodes, and are passed in the final report for the suite.
   163  ReportAfterSuite nodes must be created at the top-level (i.e. not nested in a Context/Describe/When node)
   164  
   165  When running in parallel, Ginkgo ensures that only one of the parallel nodes runs the ReportAfterSuite and that it is passed a report that is aggregated across
   166  all parallel nodes
   167  
   168  In addition to using ReportAfterSuite to programmatically generate suite reports, you can also generate JSON, JUnit, and Teamcity formatted reports using the --json-report, --junit-report, and --teamcity-report ginkgo CLI flags.
   169  
   170  You cannot nest any other Ginkgo nodes within a ReportAfterSuite node's closure.
   171  You can learn more about ReportAfterSuite here: https://onsi.github.io/ginkgo/#generating-reports-programmatically
   172  
   173  You can learn more about Ginkgo's reporting infrastructure, including generating reports with the CLI here: https://onsi.github.io/ginkgo/#generating-machine-readable-reports
   174  
   175  You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spec-timeouts-and-interruptible-nodes
   176  */
   177  func ReportAfterSuite(text string, body any, args ...interface{}) bool {
   178  	combinedArgs := []interface{}{body}
   179  	combinedArgs = append(combinedArgs, args...)
   180  	return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportAfterSuite, text, combinedArgs...))
   181  }
   182  
   183  func registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig types.ReporterConfig) {
   184  	body := func(report Report) {
   185  		if reporterConfig.JSONReport != "" {
   186  			err := reporters.GenerateJSONReport(report, reporterConfig.JSONReport)
   187  			if err != nil {
   188  				Fail(fmt.Sprintf("Failed to generate JSON report:\n%s", err.Error()))
   189  			}
   190  		}
   191  		if reporterConfig.JUnitReport != "" {
   192  			err := reporters.GenerateJUnitReport(report, reporterConfig.JUnitReport)
   193  			if err != nil {
   194  				Fail(fmt.Sprintf("Failed to generate JUnit report:\n%s", err.Error()))
   195  			}
   196  		}
   197  		if reporterConfig.TeamcityReport != "" {
   198  			err := reporters.GenerateTeamcityReport(report, reporterConfig.TeamcityReport)
   199  			if err != nil {
   200  				Fail(fmt.Sprintf("Failed to generate Teamcity report:\n%s", err.Error()))
   201  			}
   202  		}
   203  	}
   204  
   205  	flags := []string{}
   206  	if reporterConfig.JSONReport != "" {
   207  		flags = append(flags, "--json-report")
   208  	}
   209  	if reporterConfig.JUnitReport != "" {
   210  		flags = append(flags, "--junit-report")
   211  	}
   212  	if reporterConfig.TeamcityReport != "" {
   213  		flags = append(flags, "--teamcity-report")
   214  	}
   215  	pushNode(internal.NewNode(
   216  		deprecationTracker, types.NodeTypeReportAfterSuite,
   217  		fmt.Sprintf("Autogenerated ReportAfterSuite for %s", strings.Join(flags, " ")),
   218  		body,
   219  		types.NewCustomCodeLocation("autogenerated by Ginkgo"),
   220  	))
   221  }
   222  

View as plain text