Skip to content

Commit

Permalink
Merge pull request #53 from jenkinsci/junit
Browse files Browse the repository at this point in the history
Add a JUnit parser
  • Loading branch information
uhafner authored Nov 20, 2023
2 parents de84cf4 + 111cd9c commit b3577a7
Show file tree
Hide file tree
Showing 68 changed files with 1,796 additions and 186 deletions.
58 changes: 58 additions & 0 deletions src/main/java/edu/hm/hafner/coverage/ClassNode.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package edu.hm.hafner.coverage;

import java.util.ArrayList;
import java.util.List;

/**
* A {@link Node} for a specific class.
*/
public final class ClassNode extends Node {
private static final long serialVersionUID = 1621410859864978552L;

private List<TestCase> testCases = new ArrayList<>();

/**
* Creates a new {@link ClassNode} with the given name.
*
Expand All @@ -21,6 +26,18 @@ public ClassNode copy() {
return new ClassNode(getName());
}

/**
* Called after deserialization to retain backward compatibility.
*
* @return this
*/
private Object readResolve() {
if (testCases == null) {

Check warning on line 35 in src/main/java/edu/hm/hafner/coverage/ClassNode.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 35 is only partially covered, one branch is missing

Check warning on line 35 in src/main/java/edu/hm/hafner/coverage/ClassNode.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 35 (NegateConditionalsMutator)
Raw output
Survived mutations:
- negated conditional (org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator)
testCases = new ArrayList<>();

Check warning on line 36 in src/main/java/edu/hm/hafner/coverage/ClassNode.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 36 is not covered by tests
}
return this;
}

/**
* Create a new method node with the given method name and signature and add it to the list of children.
*
Expand All @@ -41,4 +58,45 @@ public MethodNode createMethodNode(final String methodName, final String signatu
public boolean isAggregation() {
return false;
}

/**
* Adds a new test case to this class.
*
* @param testCase
* the test case to add
*/
public void addTestCase(final TestCase testCase) {
testCases.add(testCase);

replaceValue(new TestCount(testCases.size()));
}

@Override
public List<TestCase> getTestCases() {
return testCases;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}

Check warning on line 89 in src/main/java/edu/hm/hafner/coverage/ClassNode.java

View check run for this annotation

ci.jenkins.io / CPD

CPD

LOW: Found duplicated code.
Raw output
<pre><code>} &#64;Override public boolean equals(final Object o) { if (this &#61;&#61; o) { return true; } if (o &#61;&#61; null || getClass() !&#61; o.getClass()) { return false; } if (!super.equals(o)) { return false; }</code></pre>

ClassNode classNode = (ClassNode) o;

return testCases.equals(classNode.testCases);
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + testCases.hashCode();
return result;
}
}
1 change: 1 addition & 0 deletions src/main/java/edu/hm/hafner/coverage/FileNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ public void addMutation(final Mutation mutation) {
mutations.add(mutation);
}

@Override
public List<Mutation> getMutations() {
return Collections.unmodifiableList(mutations);
}
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/edu/hm/hafner/coverage/Metric.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
* A coverage metric to identify the coverage result type. Note the enum order since the ordinal is used to sort the
* A metric to identify the type of the results. The enum order will be used to sort the
* values for display purposes.
*
* @author Ullrich Hafner
Expand All @@ -37,7 +37,8 @@ public enum Metric {
COMPLEXITY(new ValuesAggregator(), MetricTendency.SMALLER_IS_BETTER),
COMPLEXITY_MAXIMUM(new MethodMaxComplexityFinder(), MetricTendency.SMALLER_IS_BETTER),
COMPLEXITY_DENSITY(new DensityEvaluator(), MetricTendency.SMALLER_IS_BETTER),
LOC(new LocEvaluator(), MetricTendency.SMALLER_IS_BETTER);
LOC(new LocEvaluator(), MetricTendency.SMALLER_IS_BETTER),
TESTS(new ValuesAggregator(), MetricTendency.LARGER_IS_BETTER);

/**
* Returns the metric that belongs to the specified tag.
Expand Down Expand Up @@ -218,10 +219,10 @@ public boolean isAggregatingChildren() {

@Override
Optional<Value> compute(final Node node, final Metric searchMetric) {
if (node.getMetric() == Metric.METHOD) {
if (node.getMetric() == METHOD) {
return COMPLEXITY.getValueFor(node)
.map(c -> new CyclomaticComplexity(((CyclomaticComplexity)c).getValue(),
Metric.COMPLEXITY_MAXIMUM));
COMPLEXITY_MAXIMUM));
}
return node.getChildren().stream()
.map(c -> compute(c, searchMetric))
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/edu/hm/hafner/coverage/Mutation.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import edu.hm.hafner.util.TreeStringBuilder;

/**
* Class which represents a mutation of the PIT Mutation Testing tool.
* Represents a mutation of the PIT Mutation Testing tool.
*
* @author Melissa Bauer
*/
Expand Down
26 changes: 24 additions & 2 deletions src/main/java/edu/hm/hafner/coverage/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,20 @@ public Optional<MethodNode> findMethod(final String searchName, final String sea
.findAny();
}

public List<Mutation> getMutations() {
return getChildren().stream()
.map(Node::getMutations)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}

public List<TestCase> getTestCases() {
return getChildren().stream()
.map(Node::getTestCases)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}

/**
* Returns the file names that are contained within the subtree of this node.
*
Expand All @@ -468,11 +482,19 @@ public Set<String> getFiles() {
}

public List<FileNode> getAllFileNodes() {
return getAll(Metric.FILE).stream().map(FileNode.class::cast).collect(Collectors.toList());
return getAll(Metric.FILE, FileNode.class::cast);
}

public List<ClassNode> getAllClassNodes() {
return getAll(Metric.CLASS, ClassNode.class::cast);
}

public List<MethodNode> getAllMethodNodes() {
return getAll(Metric.METHOD).stream().map(MethodNode.class::cast).collect(Collectors.toList());
return getAll(Metric.METHOD, MethodNode.class::cast);
}

private <T extends Node> List<T> getAll(final Metric metric1, final Function<Node, T> cast) {
return getAll(metric1).stream().map(cast).collect(Collectors.toList());
}

/**
Expand Down
182 changes: 182 additions & 0 deletions src/main/java/edu/hm/hafner/coverage/TestCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package edu.hm.hafner.coverage;

import java.io.Serializable;

import org.apache.commons.lang3.StringUtils;

import com.google.errorprone.annotations.CanIgnoreReturnValue;

import edu.hm.hafner.util.Generated;

/**
* Represents a test case that has been executed.
*
* @author Ullrich Hafner
*/
public final class TestCase implements Serializable {
private static final long serialVersionUID = -2181204291759959155L;

private final String testName;
private final String className;
private final TestResult status;
private final String type;
private final String message;
private final String description;

private TestCase(final String testName, final String className, final TestResult status,
final String type, final String message, final String description) {
this.testName = testName;
this.className = className.intern();
this.status = status;
this.type = type;
this.message = message;
this.description = description;
}

public String getTestName() {
return testName;
}

public String getClassName() {
return className;
}

public TestResult getStatus() {
return status;
}

public String getType() {
return type;
}

public String getMessage() {
return message;
}

public String getDescription() {
return description;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

TestCase testCase = (TestCase) o;

if (!testName.equals(testCase.testName)) {
return false;
}
if (!className.equals(testCase.className)) {
return false;
}
if (status != testCase.status) {
return false;
}
if (!type.equals(testCase.type)) {
return false;
}
if (!message.equals(testCase.message)) {
return false;
}
return description.equals(testCase.description);
}

@Override @Generated
public String toString() {
return "TestCase{testName='" + testName + '\'' + ", className='" + className + '\'' + ", status=" + status
+ ", type='" + type + '\'' + ", message='" + message + '\'' + ", description='" + description + '\''
+ '}';
}

@Override
public int hashCode() {
int result = testName.hashCode();
result = 31 * result + className.hashCode();
result = 31 * result + status.hashCode();
result = 31 * result + type.hashCode();
result = 31 * result + message.hashCode();
result = 31 * result + description.hashCode();
return result;
}

/**
* Builder to create new {@link TestCase} instances.
*/
@SuppressWarnings({"checkstyle:MissingJavadocMethod", "checkstyle:HiddenField", "ParameterHidesMemberVariable"})
public static class TestCaseBuilder {
private TestResult status = TestResult.PASSED;
private String testName = StringUtils.EMPTY;
private String className = StringUtils.EMPTY;
private String type = StringUtils.EMPTY;
private String message = StringUtils.EMPTY;
private String description = StringUtils.EMPTY;

@CanIgnoreReturnValue
public TestCaseBuilder withStatus(final TestResult status) {
this.status = status;

return this;

Check warning on line 123 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 123 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withStatus (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withTestName(final String testName) {
this.testName = testName;

return this;

Check warning on line 130 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 130 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withTestName (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withClassName(final String className) {
this.className = className;

return this;

Check warning on line 137 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 137 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withClassName (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withType(final String type) {
this.type = type;

return this;

Check warning on line 144 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 144 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withType (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withMessage(final String message) {
this.message = message;

return this;

Check warning on line 151 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 151 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withMessage (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withDescription(final String description) {
this.description = description;

return this;

Check warning on line 158 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 158 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withDescription (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

@CanIgnoreReturnValue
public TestCaseBuilder withFailure() {
status = TestResult.FAILED;

return this;

Check warning on line 165 in src/main/java/edu/hm/hafner/coverage/TestCase.java

View check run for this annotation

ci.jenkins.io / Mutation Coverage

Mutation survived

One mutation survived in line 165 (NullReturnValsMutator)
Raw output
Survived mutations:
- replaced return value with null for edu/hm/hafner/coverage/TestCase$TestCaseBuilder::withFailure (org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator)
}

public TestCase build() {
return new TestCase(testName, className, status, type, message, description);
}
}

/**
* The result of a test case.
*/
public enum TestResult {
PASSED,
FAILED,
SKIPPED,
ABORTED
}
}
25 changes: 25 additions & 0 deletions src/main/java/edu/hm/hafner/coverage/TestCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package edu.hm.hafner.coverage;

/**
* Represents the total number of tests.
*
* @author Ullrich Hafner
*/
public final class TestCount extends IntegerValue {
private static final long serialVersionUID = -3098842770938054269L;

/**
* Creates a new {@link TestCount} instance with the number of tests.
*
* @param tests
* the number of tests
*/
public TestCount(final int tests) {
super(Metric.TESTS, tests);
}

@Override
protected IntegerValue create(final int value) {
return new TestCount(value);
}
}
2 changes: 2 additions & 0 deletions src/main/java/edu/hm/hafner/coverage/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public static Value valueOf(final String stringRepresentation) {
return new CyclomaticComplexity(Integer.parseInt(value), Metric.COMPLEXITY_MAXIMUM);
case LOC:
return new LinesOfCode(Integer.parseInt(value));
case TESTS:
return new TestCount(Integer.parseInt(value));
}
}
}
Expand Down
Loading

0 comments on commit b3577a7

Please sign in to comment.