Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add passing tests and test duration #80

Closed

Conversation

eugene-davis
Copy link

Adds to the test data that is recorded the duration of each test.
In addition, adds passing tests to the data that is recorded for tests, so that you can get duration of all tests that were run.

Unit tests have been added.


passedTests = new ArrayList<String>();
passedTestsWithDetail = new ArrayList<ExecutedTest>();
for (TestResult result : testResultAction.getPassedTests()) {

Choose a reason for hiding this comment

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

this isn't dry now, can you please refactor the logic into a helper method that will take in a collection of TestResult and fill a List and List?

Copy link
Author

Choose a reason for hiding this comment

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

I will address this shortly

Copy link
Author

Choose a reason for hiding this comment

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

This is done now, but it throws an unchecked/unsafe warning because I had to cast the return of getPassedTests/getFailedTests to List (the default return seems to be something like "capture # - TestResult"). Is there a better way to handle this or is it expected?

@@ -67,15 +67,20 @@
private final static Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getCanonicalName());
public static class TestData {
private int totalCount, skipCount, failCount, passCount;
private List<FailedTest> failedTestsWithErrorDetail;
private List<ExecutedTest> failedTestsWithDetail;

Choose a reason for hiding this comment

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

This will change the JSON format in an incompatible way
The name has to stay the same for sake of backwards compatibility

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I've left failed tests as FailedTest, but split passed tests to PassedTest (both of which inherit from the same class, ExecutedTest). That should keep the JSON format for the failed tests the same as before, but also avoid having passing tests under FailedTests.

Choose a reason for hiding this comment

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

The class name could have changed, it's only the field name that matters

Copy link
Author

Choose a reason for hiding this comment

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

Oh, sorry, that was obvious and I totally misread your first comment. I'll flip that back and remove the extra classes.

@jakub-bochenski
Copy link

@mwinter69 can you take a look too?

}
}

public static class PassedTest extends ExecutedTest {

Choose a reason for hiding this comment

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

I fail to see why are those 2 classes needed?

Copy link
Author

Choose a reason for hiding this comment

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

Will fix, see above.


passedTests = new ArrayList<String>();
passedTestsWithErrorDetail = new ArrayList<ExecutedTest>();
testListFill((List<TestResult>) testResultAction.getPassedTests(), passedTests, passedTestsWithErrorDetail);
Copy link
Author

Choose a reason for hiding this comment

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

Is there a smarter way to invoke this function than an unchecked cast?

@jakub-bochenski
Copy link

@eugene-davis sorry, I forgot to mention this at the begining

I'm worried about the amount of extra data this might generate. I assume for most builds the number of passing tests is far larger than the amount of failing tests.
I've seen many builds that execute 10k or more tests and the test output size was in GB range.

I think for this reasons sending passing tests output needs to be enabled via a configuration option.

@eugene-davis
Copy link
Author

@jakub-bochenski I will take a look at adding this option. I'll plan to add it as disabled by default.

@jakub-bochenski
Copy link

OK, the biggest challenge will be the fact that now BuildData is created independently of the configuration options.

Alternatively you could wait for #71 - this would allow people to just remove the extra data with a groovy script.

@eugene-davis
Copy link
Author

My thought was that something simple would work (but maybe it was naive - I haven't done much work with Jenkins plugins).
Something like this:
LogstashConfiguration configuration = LogstashConfiguration.getInstance();' 'if (configuration.isrecordingPassingTests()) {(set test)}

@jakub-bochenski
Copy link

Using singletons like that is generally considered an anti-pattern. I know current code is already doing that, but I'd prefer to add least not add more of it.

One way I'd suggest to refactor it is to use an abstract factory to create the BuildData, instead of using the constructor directly (as LogstashWriter does now).
The factory should probably take up most of the initData() logic as well as said "passed tests" switch.

@eugene-davis
Copy link
Author

eugene-davis commented Aug 8, 2018

@jakub-bochenski I guess I'm not totally sure what you are suggestion with regards to the singleton.
As far as I can tell, the GlobalConfiguration class that the LogstashConfiguration extends upon exists as a singleton.
Is your idea to reduce the number of places that access the singelton, and pass the reference to it during construction (e.g. in an AbstractFactory)?

Edit: The short version of the question - Is the idea to not use singletons or use one in a different way?

@jakub-bochenski
Copy link

Is your idea to reduce the number of places that access the singelton, and pass the reference to it during construction (e.g. in an AbstractFactory)?

yes, this

@mwinter69
Copy link

mwinter69 commented Aug 8, 2018

There should definitely also be the possibility to set this for the JobProperty, the notifier and the pipeline step individually overriding a centrally configured option.
One general problem I see when using it via JobProperty, globally enabled Consolelogfilter and the pipeline step is that we will send the data every time once it is available. Just imagine a post build step that is running after test data is available producing thousands of lines. This could could even create considerable load on the Mater due to serialization.
A possibility to avoid this might be to send this data only at the very end in a RunListener onCompleted or onFinalized call

@eugene-davis
Copy link
Author

Ok on both, though I may move the initial refactoring into a separate branch and possibly PR to avoid having both the functional change and refactoring all go in at once.

…rding.

Tests updated to remove references to getPassingTests
@eugene-davis
Copy link
Author

The latest commit is non-final, just tracking some changes I am using on one of my Jenkins instances related to this PR.

@@ -82,6 +83,16 @@ public void setEnableGlobally(boolean enableGlobally)
this.enableGlobally = enableGlobally;
}

public void setrecordingPassingTests(boolean recordingPassingTests)

Choose a reason for hiding this comment

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

Camel case

@@ -7,6 +7,9 @@
</f:entry>
<f:entry title="Enable Globally" field="enableGlobally" description="This will not enable it for pipeline jobs.">
<f:checkbox/>
</f:entry>
<f:entry title="Enable Globally" field="recordingPassingTests" description="This will record all passing tests in addition to failing tests.">

Choose a reason for hiding this comment

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

Title is wrong

this.recordingPassingTests = recordingPassingTests;
}

public boolean isrecordingPassingTests()

Choose a reason for hiding this comment

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

camel case

@mwinter69
Copy link

BTW, there are also skipped tests. This might be more interesting than the passed tests.

}
}

private void testListFill(List<TestResult> testResults, List<String> testNames, List<ExecutedTest> testDetails) {

Choose a reason for hiding this comment

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

Make the signature of the method
List<? extends TestResult> testResults, List<String> testNames, ...
Then you don't need the type cast when you call the method

@slxiao
Copy link

slxiao commented Oct 16, 2019

@eugene-davis why this PR is closed? it's a good feature to have test duration in JSON report

@jakub-bochenski
Copy link

@slxiao you can check the discussion above for the remaining issues.
If you need this feature don't hesitate to submit a PR yourself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants