Skip to content

Conversation

@adriansr
Copy link
Contributor

@adriansr adriansr commented Nov 15, 2021

This PR updates the pipeline tests to generate code-coverage (at the processor level) for ingest pipelines:

image

image

Screenshots taken using Report Generator.

@elasticmachine
Copy link
Collaborator

elasticmachine commented Nov 15, 2021

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview preview

Expand to view the summary

Build stats

  • Start Time: 2021-12-22T08:32:44.603+0000

  • Duration: 28 min 50 sec

  • Commit: 627102c

Test stats 🧪

Test Results
Failed 0
Passed 472
Skipped 0
Total 472

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

@adriansr
Copy link
Contributor Author

The coverage reports in CI are not including the pipeline source code:
image

Looks like by the time the report is generated, the source code is not available. @mdelapenya @mtojek can you help?

Copy link
Contributor

@mtojek mtojek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool feature, Adrian!

Looks like by the time the report is generated, the source code is not available. @mdelapenya @mtojek can you help?

First guess: I think this might be caused by having paths as names and you can't refer to these paths from the repository root.

I'm afraid that you need to analyze the Cobertura XML report manually and adjust the implementation later on. This is the path I went last time: elastic/integrations#755 (comment) and static files in #440 .

Screenshot taken from Report Generator.

If you plan to merge this feature, we'll kindly ask you to prepare a doc page describing how to use it.

return cobraext.FlagParsingError(err, cobraext.DataStreamsFlagName)
}

if testCoverage && len(dataStreams) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition was placed here to prevent coverage miscalculation. The runner is not aware of data stream presence (or being skipped) so it always assumes that all data streams have been selected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that. But given that (afaik) the CI never tests a single datastream, it would be very useful for pipeline developers to be able to run tests for a single datastream locally and get coverage results.

BranchRate float32 `xml:"branch-rate,attr"`
Complexity float32 `xml:"complexity,attr"`
Methods []*coberturaMethod `xml:"methods>method"`
Methods []*CoberturaMethod `xml:"methods>method"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mtojek mtojek requested a review from jsoriano November 16, 2021 09:54
@adriansr
Copy link
Contributor Author

adriansr commented Nov 16, 2021

@mtojek I'm not sure how it works during CI, but my understanding is that the coverage results are uploaded to GCloud storage (in

googleStorageUploadExt(bucket: getCoverageBucketURI(), credentialsId: "${JOB_GCS_EXT_CREDENTIALS}", pattern: "build/test-coverage/*.xml")
) and then downloaded before generating the Coverage report (in
googleStorageDownload(bucketUri: bucketUri, credentialsId: "${JOB_GCS_CREDENTIALS}", localDirectory: 'build/test-coverage', pathPrefix: getCoveragePathPrefix())
).

The generated coverage file contains absolute paths to the code. For example in zoom package, during a local run:

  <sources>
    <source>/Users/adrian/go/src/github.com/elastic/integrations/packages/zoom</source>
  </sources>

and then:

        <class name="account" filename="data_stream/webhook/elasticsearch/ingest_pipeline/account.yml" line-rate="0" branch-rate="0" complexity="0">

My understanding is that when the report is generated, the source code is not available at this path, but I don't understand in what context the coverageReport function is executed (can't find a definition for it). Maybe @mdelapenya could chime in as I see that he wrote the coverage handling in Jenkinsfile.

@jsoriano
Copy link
Member

coverageReport is defined here: https://github.com/elastic/apm-pipeline-library/blob/4a58b62664d47cb32e6c2924baf75627bf8346c9/vars/coverageReport.groovy

if tcd.cobertura != nil && result.Coverage != nil {
tcd.cobertura.Merge(result.Coverage)
} else {
tcd.cobertura = result.Coverage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if result.Coverage is nil and tcd.cobertura is not? In that line we will be setting the latter to nil. Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks

}

// Merge merges two coverage reports for a given class.
func (c *CoberturaClass) Merge(b *CoberturaClass) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see feasible adding unit tests for this method? I see a lot of calculations that would benefit for the tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"gopkg.in/yaml.v3"
)

type Processor struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see feasible adding unit tests for this method? I see a lot of calculations that would benefit for the tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@jsoriano jsoriano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @adriansr, this is great!

Is there something else keeping this as draft?

"github.com/elastic/go-elasticsearch/v7"
"github.com/pkg/errors"

es "github.com/elastic/elastic-package/internal/elasticsearch"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to reduce the need of these es aliases in #596.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if err := entry.Content[0].Decode(&proc.Type); err != nil {
return nil, errors.Wrapf(err, "error decoding processor#%d type", idx)
}
proc.Line = entry.Line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. Could the Line of the last Content be used as the last line of the processor so we have per-line coverage instead of per-processor coverage? (and Cobertura paints red/green the whole processor 🙂)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, done.

Originally I decided against it because it will mark the inner processors of a compound processor as covered (inner processor of foreach, and on_failure processors), while ES doesn't provide coverage information for those.

@adriansr
Copy link
Contributor Author

This is currently waiting for the required CI fixes to have source code displayed in Jenkins coverage reports.

Once that is sorted out I'll make any required adjustments to the format (for now only tested it with a different coverage tool) and prepare the new documentation.

@adriansr adriansr marked this pull request as ready for review December 22, 2021 09:03
@adriansr adriansr changed the title [Draft] Report ingest pipeline processor coverage Report ingest pipeline processor coverage Dec 22, 2021
@elasticmachine
Copy link
Collaborator

Pinging @elastic/integrations (Team:Integrations)

@adriansr
Copy link
Contributor Author

This is ready to review pending adjustments to CI in order to make the new source code reports available.

Updated docs at elastic/integrations#2371

@mtojek
Copy link
Contributor

mtojek commented Dec 22, 2021

We collect Cobertura reports also for elastic-package. @adriansr Could you please double check if this new feature is enabled also here?

Copy link
Contributor

@mtojek mtojek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, this PR is massive. Do you think you can split it into smaller, reviewable chunks? It would be easier to fully understand what's going on behind the scenes.

// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package node_stats
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename it to nodestats.

)

// Get returns a coverage report for the provided set of ingest pipelines.
func Get(options testrunner.TestOptions, pipelines []pipeline.Resource) (*testrunner.CoberturaCoverage, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a bit of spaghetti code that has to be untangled first. Code coverage isn't the responsibility of Elasticsearch client or Pipeline, but test runners and it should stay there.

I suggest refactoring (moving around) this dependency first, then we can continue reviewing as this PR is relatively big.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Team:Integrations Label for the Integrations team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants