prow/spyglass/lenses/junit/lens.go
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	type testResults struct {
		junit []junit.Result
		link  string
		path  string
		err   error
	}
	resultChan := make(chan testResults)
	for _, artifact := range artifacts {
		go func(artifact lenses.Artifact) {
			result := testResults{
				link: artifact.CanonicalLink(),
				path: artifact.JobPath(),
			}
			var contents []byte
			contents, result.err = artifact.ReadAll()
			if result.err != nil {
				logrus.WithError(result.err).WithField("artifact", artifact.CanonicalLink()).Warn("Error reading artifact")
				resultChan <- result
				return
			}
			var suites junit.Suites
			suites, result.err = junit.Parse(contents)
			if result.err != nil {
				logrus.WithError(result.err).WithField("artifact", artifact.CanonicalLink()).Info("Error parsing junit file.")
				resultChan <- result
				return
			}
			for _, suite := range suites.Suites {
				for _, test := range suite.Results {
					result.junit = append(result.junit, test)
				}
			}
			resultChan <- result
		}(artifact)
	}
	results := make([]testResults, 0, len(artifacts))
	for range artifacts {
		results = append(results, <-resultChan)
	}
	sort.Slice(results, func(i, j int) bool { return results[i].path < results[j].path })

	jvd := struct {
		NumTests int
		Passed   []TestResult
		Failed   []TestResult
		Skipped  []TestResult
	}{}
	for _, result := range results {
		if result.err != nil {
			continue
		}
		for _, test := range result.junit {
			if test.Failure != nil {
				jvd.Failed = append(jvd.Failed, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			} else if test.Skipped != nil {
				jvd.Skipped = append(jvd.Skipped, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			} else {
				jvd.Passed = append(jvd.Passed, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			}
		}
	}

	jvd.NumTests = len(jvd.Passed) + len(jvd.Failed) + len(jvd.Skipped)

	junitTemplate, err := template.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		logrus.WithError(err).Error("Error executing template.")
		return fmt.Sprintf("Failed to load template file: %v", err)
	}

	var buf bytes.Buffer
	if err := junitTemplate.ExecuteTemplate(&buf, "body", jvd); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}

	return buf.String()
}
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	type testResults struct {
		junit []junit.Result
		link  string
		path  string
		err   error
	}
	resultChan := make(chan testResults)
	for _, artifact := range artifacts {
		go func(artifact lenses.Artifact) {
			result := testResults{
				link: artifact.CanonicalLink(),
				path: artifact.JobPath(),
			}
			var contents []byte
			contents, result.err = artifact.ReadAll()
			if result.err != nil {
				logrus.WithError(result.err).WithField("artifact", artifact.CanonicalLink()).Warn("Error reading artifact")
				resultChan <- result
				return
			}
			var suites junit.Suites
			suites, result.err = junit.Parse(contents)
			if result.err != nil {
				logrus.WithError(result.err).WithField("artifact", artifact.CanonicalLink()).Info("Error parsing junit file.")
				resultChan <- result
				return
			}
			for _, suite := range suites.Suites {
				for _, test := range suite.Results {
					result.junit = append(result.junit, test)
				}
			}
			resultChan <- result
		}(artifact)
	}
	results := make([]testResults, 0, len(artifacts))
	for range artifacts {
		results = append(results, <-resultChan)
	}
	sort.Slice(results, func(i, j int) bool { return results[i].path < results[j].path })

	jvd := struct {
		NumTests int
		Passed   []TestResult
		Failed   []TestResult
		Skipped  []TestResult
	}{}
	for _, result := range results {
		if result.err != nil {
			continue
		}
		for _, test := range result.junit {
			if test.Failure != nil {
				jvd.Failed = append(jvd.Failed, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			} else if test.Skipped != nil {
				jvd.Skipped = append(jvd.Skipped, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			} else {
				jvd.Passed = append(jvd.Passed, TestResult{
					Junit: JunitResult{test},
					Link:  result.link,
				})
			}
		}
	}

	jvd.NumTests = len(jvd.Passed) + len(jvd.Failed) + len(jvd.Skipped)

	junitTemplate, err := template.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		logrus.WithError(err).Error("Error executing template.")
		return fmt.Sprintf("Failed to load template file: %v", err)
	}

	var buf bytes.Buffer
	if err := junitTemplate.ExecuteTemplate(&buf, "body", jvd); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}

	return buf.String()
}
// Body renders the <body> for JUnit tests