From 7df58c2fc0dbab0d82c5587104a9ad1d2fa369ac Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 13 Oct 2014 15:08:30 +0200 Subject: SONAR-5389 Refactor test coverage API --- .../org/sonar/api/batch/sensor/SensorContext.java | 18 +- .../org/sonar/api/batch/sensor/SensorStorage.java | 7 +- .../dependency/internal/DefaultDependency.java | 20 +-- .../api/batch/sensor/internal/DefaultStorable.java | 56 ++++++ .../batch/sensor/issue/internal/DefaultIssue.java | 18 +- .../sensor/measure/internal/DefaultMeasure.java | 21 +-- .../org/sonar/api/batch/sensor/test/TestCase.java | 125 ------------- .../api/batch/sensor/test/TestCaseCoverage.java | 77 ++++++++ .../api/batch/sensor/test/TestCaseExecution.java | 125 +++++++++++++ .../sensor/test/internal/DefaultTestCase.java | 198 --------------------- .../test/internal/DefaultTestCaseCoverage.java | 138 ++++++++++++++ .../test/internal/DefaultTestCaseExecution.java | 181 +++++++++++++++++++ .../src/main/java/org/sonar/api/test/TestCase.java | 2 +- .../internal/DefaultTestCaseExecutionTest.java | 123 +++++++++++++ .../sensor/test/internal/DefaultTestCaseTest.java | 123 ------------- 15 files changed, 729 insertions(+), 503 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseCoverage.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseExecution.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseCoverage.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecution.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecutionTest.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java (limited to 'sonar-plugin-api') diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 831ea878114..865fff64c9e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -30,7 +30,8 @@ import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; -import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.TestCaseCoverage; +import org.sonar.api.batch.sensor.test.TestCaseExecution; import org.sonar.api.config.Settings; import java.io.Serializable; @@ -112,21 +113,18 @@ public interface SensorContext { // ------------ TESTS ------------ /** - * Create a new test case. - * Don't forget to call {@link TestCase#save()} once all parameters are provided. + * Create a new test case execution report. + * Don't forget to call {@link TestCaseExecution#save()} once all parameters are provided. * @since 5.0 */ - TestCase newTestCase(); + TestCaseExecution newTestCaseExecution(); /** - * Register coverage of a given test case on another main file. TestCase should have been registered using {@link #testPlanBuilder(InputFile)} - * @param testFile test file containing the test case - * @param testCaseName name of the test case - * @param coveredFile main file that is covered - * @param coveredLines list of covered lines + * Create a new test case coverage report. + * Don't forget to call {@link TestCaseCoverage#save()} once all parameters are provided. * @since 5.0 */ - void saveCoveragePerTest(TestCase testCase, InputFile coveredFile, List coveredLines); + TestCaseCoverage newTestCaseCoverage(); // ------------ DEPENDENCIES ------------ diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorStorage.java index 7faec27f4c6..3eb8612d94b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorStorage.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorStorage.java @@ -22,7 +22,8 @@ package org.sonar.api.batch.sensor; import org.sonar.api.batch.sensor.dependency.Dependency; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; -import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.TestCaseCoverage; +import org.sonar.api.batch.sensor.test.TestCaseExecution; /** * Interface for storing data computed by sensors. @@ -34,8 +35,10 @@ public interface SensorStorage { void store(Issue issue); - void store(TestCase testCase); + void store(TestCaseExecution testCaseExecution); void store(Dependency dependency); + void store(TestCaseCoverage testCaseCoverage); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/dependency/internal/DefaultDependency.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/dependency/internal/DefaultDependency.java index 34a91f80756..9915ab48e92 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/dependency/internal/DefaultDependency.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/dependency/internal/DefaultDependency.java @@ -22,28 +22,26 @@ package org.sonar.api.batch.sensor.dependency.internal; import com.google.common.base.Preconditions; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.sensor.SensorStorage; import org.sonar.api.batch.sensor.dependency.Dependency; +import org.sonar.api.batch.sensor.internal.DefaultStorable; import javax.annotation.Nullable; -public class DefaultDependency implements Dependency { +public class DefaultDependency extends DefaultStorable implements Dependency { - private final SensorStorage storage; private InputFile from; private InputFile to; private int weight = 1; private boolean saved = false; public DefaultDependency() { - this.storage = null; + super(null); } public DefaultDependency(@Nullable SensorStorage storage) { - this.storage = storage; + super(storage); } @Override @@ -68,14 +66,11 @@ public class DefaultDependency implements Dependency { } @Override - public void save() { - Preconditions.checkNotNull(this.storage, "No persister on this object"); - Preconditions.checkState(!saved, "This dependency was already saved"); + public void doSave() { Preconditions.checkState(!this.from.equals(this.to), "From and To can't be the same inputFile"); Preconditions.checkNotNull(this.from, "From inputFile can't be null"); Preconditions.checkNotNull(this.to, "To inputFile can't be null"); storage.store((Dependency) this); - this.saved = true; } @Override @@ -123,9 +118,4 @@ public class DefaultDependency implements Dependency { toHashCode(); } - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } - } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java new file mode 100644 index 00000000000..9b1c9fa113c --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.internal; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.batch.sensor.SensorStorage; + +import javax.annotation.Nullable; + +public abstract class DefaultStorable { + + protected transient final SensorStorage storage; + private transient boolean saved = false; + + public DefaultStorable() { + this.storage = null; + } + + public DefaultStorable(@Nullable SensorStorage storage) { + this.storage = storage; + } + + public final void save() { + Preconditions.checkNotNull(this.storage, "No persister on this object"); + Preconditions.checkState(!saved, "This measure was already saved"); + doSave(); + this.saved = true; + } + + protected abstract void doSave(); + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java index 42637fdd4cb..ab7912cc8a8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java @@ -21,12 +21,11 @@ package org.sonar.api.batch.sensor.issue.internal; import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputPath; import org.sonar.api.batch.sensor.SensorStorage; +import org.sonar.api.batch.sensor.internal.DefaultStorable; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.rule.RuleKey; @@ -35,7 +34,7 @@ import javax.annotation.Nullable; import java.util.UUID; -public class DefaultIssue implements Issue { +public class DefaultIssue extends DefaultStorable implements Issue { private static final String INPUT_DIR_SHOULD_BE_NON_NULL = "InputDir should be non null"; private static final String INPUT_FILE_SHOULD_BE_NON_NULL = "InputFile should be non null"; @@ -49,16 +48,15 @@ public class DefaultIssue implements Issue { private Integer line; private Double effortToFix; private Severity overridenSeverity; - private final SensorStorage storage; public DefaultIssue() { + super(null); this.key = UUID.randomUUID().toString(); - this.storage = null; } public DefaultIssue(SensorStorage storage) { + super(storage); this.key = UUID.randomUUID().toString(); - this.storage = storage; } @Override @@ -154,11 +152,9 @@ public class DefaultIssue implements Issue { } @Override - public void save() { - Preconditions.checkNotNull(this.storage, "No persister on this object"); + public void doSave() { Preconditions.checkNotNull(this.ruleKey, "ruleKey is mandatory on issue"); Preconditions.checkState(!Strings.isNullOrEmpty(key), "Fail to generate issue key"); - storage.store(this); } @@ -187,8 +183,4 @@ public class DefaultIssue implements Issue { return key.hashCode(); } - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java index 29b5c92bc2c..167f9e6af98 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java @@ -22,11 +22,10 @@ package org.sonar.api.batch.sensor.measure.internal; import com.google.common.base.Preconditions; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.sensor.SensorStorage; +import org.sonar.api.batch.sensor.internal.DefaultStorable; import org.sonar.api.batch.sensor.measure.Measure; import javax.annotation.CheckForNull; @@ -34,22 +33,20 @@ import javax.annotation.Nullable; import java.io.Serializable; -public class DefaultMeasure implements Measure { +public class DefaultMeasure extends DefaultStorable implements Measure { - private final SensorStorage storage; private boolean onProject = false; private InputFile file; private Metric metric; private G value; - private boolean saved = false; private boolean fromCore = false; public DefaultMeasure() { - this.storage = null; + super(); } public DefaultMeasure(@Nullable SensorStorage storage) { - this.storage = storage; + super(storage); } @Override @@ -101,14 +98,11 @@ public class DefaultMeasure implements Measure { } @Override - public void save() { - Preconditions.checkNotNull(this.storage, "No persister on this object"); - Preconditions.checkState(!saved, "This measure was already saved"); + public void doSave() { Preconditions.checkNotNull(this.value, "Measure value can't be null"); Preconditions.checkNotNull(this.metric, "Measure metric can't be null"); Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type " + this.metric.valueType()); storage.store((Measure) this); - this.saved = true; } @Override @@ -157,9 +151,4 @@ public class DefaultMeasure implements Measure { toHashCode(); } - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } - } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java deleted file mode 100644 index 37b1047bec2..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.batch.sensor.test; - -import org.sonar.api.batch.fs.InputFile; - -import javax.annotation.Nullable; - -/** - * Represents a single test in a test file. - * @since 5.0 - */ -public interface TestCase { - - /** - * Test execution status. - */ - enum Status { - OK, FAILURE, ERROR, SKIPPED; - - public static Status of(@Nullable String s) { - return s == null ? null : valueOf(s.toUpperCase()); - } - } - - /** - * Test type. - */ - enum Type { - UNIT, INTEGRATION; - } - - /** - * InputFile where this test is located. - */ - InputFile testFile(); - - /** - * Set file where this test is located. Mandatory. - */ - TestCase inTestFile(InputFile testFile); - - /** - * Duration in milliseconds - */ - Long durationInMs(); - - /** - * Duration in milliseconds - */ - TestCase durationInMs(long duration); - - /** - * Name of this test case. - */ - String name(); - - /** - * Set name of this test. Name is mandatory. - */ - TestCase name(String name); - - /** - * Status of execution of the test. - */ - Status status(); - - /** - * Status of execution of the test. - */ - TestCase status(Status status); - - /** - * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). - */ - String message(); - - /** - * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). - */ - TestCase message(String message); - - /** - * Type of test. - */ - Type type(); - - /** - * Type of test. - */ - TestCase ofType(Type type); - - /** - * Stacktrace (usually in case of {@link Status#ERROR}). - */ - String stackTrace(); - - /** - * Set stacktrace (usually in case of {@link Status#ERROR}). - */ - TestCase stackTrace(String stackTrace); - - /** - * Call this method only once when your are done with defining the test case. - */ - void save(); - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseCoverage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseCoverage.java new file mode 100644 index 00000000000..4d620428d11 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseCoverage.java @@ -0,0 +1,77 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.test; + +import org.sonar.api.batch.fs.InputFile; + +import java.util.List; + +/** + * Represents line coverage produced by a single test in a test file on a single main file. + * @since 5.0 + */ +public interface TestCaseCoverage { + + /** + * InputFile where this test is located. + */ + InputFile testFile(); + + /** + * Set file where this test is located. Mandatory. + */ + TestCaseCoverage testFile(InputFile testFile); + + /** + * Name of this test case. + */ + String testName(); + + /** + * Set name of this test. Name is mandatory. + */ + TestCaseCoverage testName(String name); + + /** + * InputFile covered by this test. + */ + InputFile coveredFile(); + + /** + * Set file covered by this test. Mandatory. + */ + TestCaseCoverage cover(InputFile mainFile); + + /** + * List of line numbers (1-based) covered by this test. + */ + List coveredLines(); + + /** + * Set list of line numbers (1-based) covered by this test. Mandatory. + */ + TestCaseCoverage onLines(List lines); + + /** + * Call this method only once when your are done with defining the test case coverage. + */ + void save(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseExecution.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseExecution.java new file mode 100644 index 00000000000..9a9bf4bb072 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseExecution.java @@ -0,0 +1,125 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.test; + +import org.sonar.api.batch.fs.InputFile; + +import javax.annotation.Nullable; + +/** + * Represents result of execution of a single test in a test file. + * @since 5.0 + */ +public interface TestCaseExecution { + + /** + * Test execution status. + */ + enum Status { + OK, FAILURE, ERROR, SKIPPED; + + public static Status of(@Nullable String s) { + return s == null ? null : valueOf(s.toUpperCase()); + } + } + + /** + * Test type. + */ + enum Type { + UNIT, INTEGRATION; + } + + /** + * InputFile where this test is located. + */ + InputFile testFile(); + + /** + * Set file where this test is located. Mandatory. + */ + TestCaseExecution inTestFile(InputFile testFile); + + /** + * Duration in milliseconds + */ + Long durationInMs(); + + /** + * Duration in milliseconds + */ + TestCaseExecution durationInMs(long duration); + + /** + * Name of this test case. + */ + String name(); + + /** + * Set name of this test. Name is mandatory. + */ + TestCaseExecution name(String name); + + /** + * Status of execution of the test. + */ + Status status(); + + /** + * Status of execution of the test. + */ + TestCaseExecution status(Status status); + + /** + * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). + */ + String message(); + + /** + * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). + */ + TestCaseExecution message(String message); + + /** + * Type of test. + */ + Type type(); + + /** + * Type of test. + */ + TestCaseExecution ofType(Type type); + + /** + * Stacktrace (usually in case of {@link Status#ERROR}). + */ + String stackTrace(); + + /** + * Set stacktrace (usually in case of {@link Status#ERROR}). + */ + TestCaseExecution stackTrace(String stackTrace); + + /** + * Call this method only once when your are done with defining the test case execution. + */ + void save(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java deleted file mode 100644 index 100b0545980..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.batch.sensor.test.internal; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.sensor.SensorStorage; -import org.sonar.api.batch.sensor.test.TestCase; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -public class DefaultTestCase implements TestCase { - - private final SensorStorage storage; - private InputFile testFile; - private String name; - private Long duration; - private TestCase.Status status = Status.OK; - private String message; - private TestCase.Type type = Type.UNIT; - private String stackTrace; - - public DefaultTestCase() { - this.storage = null; - } - - public DefaultTestCase(SensorStorage storage) { - this.storage = storage; - } - - @Override - public DefaultTestCase inTestFile(InputFile testFile) { - Preconditions.checkNotNull(testFile, "TestFile cannot be null"); - Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); - this.testFile = testFile; - return this; - } - - @Override - public DefaultTestCase name(String name) { - Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name is mandatory and should not be blank"); - this.name = name; - return this; - } - - @Override - public DefaultTestCase durationInMs(long duration) { - Preconditions.checkArgument(duration >= 0, "Test duration must be positive (got: " + duration + ")"); - this.duration = duration; - return this; - } - - @Override - public DefaultTestCase status(TestCase.Status status) { - Preconditions.checkNotNull(status); - this.status = status; - return this; - } - - @Override - public DefaultTestCase message(@Nullable String message) { - this.message = message; - return this; - } - - @Override - public DefaultTestCase ofType(TestCase.Type type) { - Preconditions.checkNotNull(type); - this.type = type; - return this; - } - - @Override - public DefaultTestCase stackTrace(@Nullable String stackTrace) { - this.stackTrace = stackTrace; - return this; - } - - @Override - public InputFile testFile() { - return testFile; - } - - @CheckForNull - @Override - public Long durationInMs() { - return duration; - } - - @Override - public Type type() { - return type; - } - - @Override - public Status status() { - return status; - } - - @Override - public String name() { - return name; - } - - @CheckForNull - @Override - public String message() { - return message; - } - - @CheckForNull - @Override - public String stackTrace() { - return stackTrace; - } - - @Override - public void save() { - Preconditions.checkNotNull(this.storage, "No persister on this object"); - Preconditions.checkNotNull(testFile, "TestFile is mandatory"); - Preconditions.checkNotNull(name, "TestFile is mandatory"); - storage.store(this); - } - - // Just for unit tests - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - DefaultTestCase rhs = (DefaultTestCase) obj; - return new EqualsBuilder() - .append(testFile, rhs.testFile) - .append(name, rhs.name) - .append(duration, rhs.duration) - .append(status, rhs.status) - .append(message, rhs.message) - .append(type, rhs.type) - .append(stackTrace, rhs.stackTrace) - .isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(13, 43) - .append(testFile) - .append(name) - .append(duration) - .append(status) - .append(message) - .append(type) - .append(stackTrace) - .toHashCode(); - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) - .append("file", testFile) - .append("name", name) - .append("duration", duration) - .append("status", status) - .append("message", message) - .append("type", type) - .append("stackTrace", stackTrace) - .toString(); - } - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseCoverage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseCoverage.java new file mode 100644 index 00000000000..f2f8834d87f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseCoverage.java @@ -0,0 +1,138 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.test.internal; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.SensorStorage; +import org.sonar.api.batch.sensor.internal.DefaultStorable; +import org.sonar.api.batch.sensor.test.TestCaseCoverage; + +import java.util.Collections; +import java.util.List; + +public class DefaultTestCaseCoverage extends DefaultStorable implements TestCaseCoverage { + + private InputFile testFile; + private InputFile mainFile; + private String name; + private List lines; + + public DefaultTestCaseCoverage() { + super(null); + } + + public DefaultTestCaseCoverage(SensorStorage storage) { + super(storage); + } + + @Override + public InputFile testFile() { + return testFile; + } + + @Override + public DefaultTestCaseCoverage testFile(InputFile testFile) { + Preconditions.checkNotNull(testFile, "TestFile cannot be null"); + Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); + this.testFile = testFile; + return this; + } + + @Override + public InputFile coveredFile() { + return mainFile; + } + + @Override + public TestCaseCoverage cover(InputFile mainFile) { + Preconditions.checkNotNull(mainFile, "InputFile cannot be null"); + Preconditions.checkArgument(mainFile.type() == InputFile.Type.MAIN, "Should be a main file: " + mainFile); + this.mainFile = mainFile; + return this; + } + + @Override + public DefaultTestCaseCoverage testName(String name) { + Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name is mandatory and should not be blank"); + this.name = name; + return this; + } + + @Override + public String testName() { + return name; + } + + @Override + public List coveredLines() { + return Collections.unmodifiableList(lines); + } + + @Override + public TestCaseCoverage onLines(List lines) { + Preconditions.checkNotNull(lines, "Lines list cannot be null"); + Preconditions.checkArgument(lines.size() > 0, "No need to register test coverage if no line is covered"); + this.lines = lines; + return this; + } + + @Override + public void doSave() { + Preconditions.checkNotNull(testFile, "TestFile is mandatory"); + Preconditions.checkNotNull(mainFile, "MainFile is mandatory"); + Preconditions.checkNotNull(name, "Test name is mandatory"); + Preconditions.checkNotNull(lines, "Lines are mandatory"); + storage.store(this); + } + + // Just for unit tests + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + DefaultTestCaseCoverage rhs = (DefaultTestCaseCoverage) obj; + return new EqualsBuilder() + .append(testFile, rhs.testFile) + .append(name, rhs.name) + .append(mainFile, rhs.mainFile) + .append(lines.toArray(), rhs.lines.toArray()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(13, 43) + .append(testFile) + .append(name) + .append(mainFile) + .toHashCode(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecution.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecution.java new file mode 100644 index 00000000000..550fd83e9ab --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecution.java @@ -0,0 +1,181 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.test.internal; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.SensorStorage; +import org.sonar.api.batch.sensor.internal.DefaultStorable; +import org.sonar.api.batch.sensor.test.TestCaseExecution; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class DefaultTestCaseExecution extends DefaultStorable implements TestCaseExecution { + + private InputFile testFile; + private String name; + private Long duration; + private TestCaseExecution.Status status = Status.OK; + private String message; + private TestCaseExecution.Type type = Type.UNIT; + private String stackTrace; + + public DefaultTestCaseExecution() { + super(null); + } + + public DefaultTestCaseExecution(SensorStorage storage) { + super(storage); + } + + @Override + public DefaultTestCaseExecution inTestFile(InputFile testFile) { + Preconditions.checkNotNull(testFile, "TestFile cannot be null"); + Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); + this.testFile = testFile; + return this; + } + + @Override + public DefaultTestCaseExecution name(String name) { + Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name is mandatory and should not be blank"); + this.name = name; + return this; + } + + @Override + public DefaultTestCaseExecution durationInMs(long duration) { + Preconditions.checkArgument(duration >= 0, "Test duration must be positive (got: " + duration + ")"); + this.duration = duration; + return this; + } + + @Override + public DefaultTestCaseExecution status(TestCaseExecution.Status status) { + Preconditions.checkNotNull(status); + this.status = status; + return this; + } + + @Override + public DefaultTestCaseExecution message(@Nullable String message) { + this.message = message; + return this; + } + + @Override + public DefaultTestCaseExecution ofType(TestCaseExecution.Type type) { + Preconditions.checkNotNull(type); + this.type = type; + return this; + } + + @Override + public DefaultTestCaseExecution stackTrace(@Nullable String stackTrace) { + this.stackTrace = stackTrace; + return this; + } + + @Override + public InputFile testFile() { + return testFile; + } + + @CheckForNull + @Override + public Long durationInMs() { + return duration; + } + + @Override + public Type type() { + return type; + } + + @Override + public Status status() { + return status; + } + + @Override + public String name() { + return name; + } + + @CheckForNull + @Override + public String message() { + return message; + } + + @CheckForNull + @Override + public String stackTrace() { + return stackTrace; + } + + @Override + public void doSave() { + Preconditions.checkNotNull(testFile, "TestFile is mandatory"); + Preconditions.checkNotNull(name, "Test name is mandatory"); + storage.store(this); + } + + // Just for unit tests + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + DefaultTestCaseExecution rhs = (DefaultTestCaseExecution) obj; + return new EqualsBuilder() + .append(testFile, rhs.testFile) + .append(name, rhs.name) + .append(duration, rhs.duration) + .append(status, rhs.status) + .append(message, rhs.message) + .append(type, rhs.type) + .append(stackTrace, rhs.stackTrace) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(13, 43) + .append(testFile) + .append(name) + .append(duration) + .append(status) + .append(message) + .append(type) + .append(stackTrace) + .toHashCode(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java index 70dccba3976..15dd571699e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java @@ -22,7 +22,7 @@ package org.sonar.api.test; import javax.annotation.Nullable; /** - * @deprecated since 5.0 see {@link org.sonar.api.batch.sensor.test.TestCase} + * @deprecated since 5.0 see {@link org.sonar.api.batch.sensor.test.TestCaseExecution} */ @Deprecated public interface TestCase { diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecutionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecutionTest.java new file mode 100644 index 00000000000..01abb7965ff --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseExecutionTest.java @@ -0,0 +1,123 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.test.internal; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.test.TestCaseExecution.Status; +import org.sonar.api.batch.sensor.test.TestCaseExecution.Type; + +import static org.fest.assertions.Assertions.assertThat; + +public class DefaultTestCaseExecutionTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private InputFile parent = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.TEST); + + @Test + public void testCreation() throws Exception { + DefaultTestCaseExecution testCase = new DefaultTestCaseExecution(null) + .inTestFile(parent) + .name("myTest") + .durationInMs(1) + .message("message") + .stackTrace("stack") + .status(Status.ERROR) + .ofType(Type.UNIT); + + assertThat(testCase.name()).isEqualTo("myTest"); + assertThat(testCase.testFile()).isEqualTo(parent); + assertThat(testCase.durationInMs()).isEqualTo(1L); + assertThat(testCase.message()).isEqualTo("message"); + assertThat(testCase.stackTrace()).isEqualTo("stack"); + assertThat(testCase.status()).isEqualTo(Status.ERROR); + assertThat(testCase.type()).isEqualTo(Type.UNIT); + } + + @Test + public void testCreationWithDefaultValues() throws Exception { + DefaultTestCaseExecution testCase = new DefaultTestCaseExecution(null) + .inTestFile(parent) + .name("myTest"); + + assertThat(testCase.name()).isEqualTo("myTest"); + assertThat(testCase.testFile()).isEqualTo(parent); + assertThat(testCase.durationInMs()).isNull(); + assertThat(testCase.message()).isNull(); + assertThat(testCase.stackTrace()).isNull(); + assertThat(testCase.status()).isEqualTo(Status.OK); + assertThat(testCase.type()).isEqualTo(Type.UNIT); + } + + @Test + public void testInvalidDuration() throws Exception { + DefaultTestCaseExecution builder = new DefaultTestCaseExecution(null) + .inTestFile(parent) + .name("myTest"); + + thrown.expect(IllegalArgumentException.class); + + builder.durationInMs(-3); + } + + @Test + public void testEqualsHashCodeToString() { + DefaultTestCaseExecution testCase1 = new DefaultTestCaseExecution(null) + .inTestFile(parent) + .name("myTest") + .durationInMs(1) + .message("message") + .stackTrace("stack") + .status(Status.ERROR) + .ofType(Type.UNIT); + DefaultTestCaseExecution testCase1a = new DefaultTestCaseExecution(null) + .inTestFile(parent) + .name("myTest") + .durationInMs(1) + .message("message") + .stackTrace("stack") + .status(Status.ERROR) + .ofType(Type.UNIT); + DefaultTestCaseExecution testCase2 = new DefaultTestCaseExecution(null) + .inTestFile(new DefaultInputFile("foo2", "src/Foo.php").setType(InputFile.Type.TEST)) + .name("myTest2") + .durationInMs(2) + .message("message2") + .stackTrace("null") + .status(Status.FAILURE) + .ofType(Type.INTEGRATION); + + assertThat(testCase1).isEqualTo(testCase1); + assertThat(testCase1).isEqualTo(testCase1a); + assertThat(testCase1).isNotEqualTo(testCase2); + assertThat(testCase1).isNotEqualTo(null); + assertThat(testCase1).isNotEqualTo("foo"); + + assertThat(testCase1.toString()).isEqualTo( + "DefaultTestCaseExecution[testFile=[moduleKey=foo, relative=src/Foo.php, abs=null],name=myTest,duration=1,status=ERROR,message=message,type=UNIT,stackTrace=stack]"); + assertThat(testCase1.hashCode()).isEqualTo(testCase1a.hashCode()); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java deleted file mode 100644 index a987eb155d4..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.batch.sensor.test.internal; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.test.TestCase.Status; -import org.sonar.api.batch.sensor.test.TestCase.Type; - -import static org.fest.assertions.Assertions.assertThat; - -public class DefaultTestCaseTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private InputFile parent = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.TEST); - - @Test - public void testCreation() throws Exception { - DefaultTestCase testCase = new DefaultTestCase(null) - .inTestFile(parent) - .name("myTest") - .durationInMs(1) - .message("message") - .stackTrace("stack") - .status(Status.ERROR) - .ofType(Type.UNIT); - - assertThat(testCase.name()).isEqualTo("myTest"); - assertThat(testCase.testFile()).isEqualTo(parent); - assertThat(testCase.durationInMs()).isEqualTo(1L); - assertThat(testCase.message()).isEqualTo("message"); - assertThat(testCase.stackTrace()).isEqualTo("stack"); - assertThat(testCase.status()).isEqualTo(Status.ERROR); - assertThat(testCase.type()).isEqualTo(Type.UNIT); - } - - @Test - public void testCreationWithDefaultValues() throws Exception { - DefaultTestCase testCase = new DefaultTestCase(null) - .inTestFile(parent) - .name("myTest"); - - assertThat(testCase.name()).isEqualTo("myTest"); - assertThat(testCase.testFile()).isEqualTo(parent); - assertThat(testCase.durationInMs()).isNull(); - assertThat(testCase.message()).isNull(); - assertThat(testCase.stackTrace()).isNull(); - assertThat(testCase.status()).isEqualTo(Status.OK); - assertThat(testCase.type()).isEqualTo(Type.UNIT); - } - - @Test - public void testInvalidDuration() throws Exception { - DefaultTestCase builder = new DefaultTestCase(null) - .inTestFile(parent) - .name("myTest"); - - thrown.expect(IllegalArgumentException.class); - - builder.durationInMs(-3); - } - - @Test - public void testEqualsHashCodeToString() { - DefaultTestCase testCase1 = new DefaultTestCase(null) - .inTestFile(parent) - .name("myTest") - .durationInMs(1) - .message("message") - .stackTrace("stack") - .status(Status.ERROR) - .ofType(Type.UNIT); - DefaultTestCase testCase1a = new DefaultTestCase(null) - .inTestFile(parent) - .name("myTest") - .durationInMs(1) - .message("message") - .stackTrace("stack") - .status(Status.ERROR) - .ofType(Type.UNIT); - DefaultTestCase testCase2 = new DefaultTestCase(null) - .inTestFile(new DefaultInputFile("foo2", "src/Foo.php").setType(InputFile.Type.TEST)) - .name("myTest2") - .durationInMs(2) - .message("message2") - .stackTrace("null") - .status(Status.FAILURE) - .ofType(Type.INTEGRATION); - - assertThat(testCase1).isEqualTo(testCase1); - assertThat(testCase1).isEqualTo(testCase1a); - assertThat(testCase1).isNotEqualTo(testCase2); - assertThat(testCase1).isNotEqualTo(null); - assertThat(testCase1).isNotEqualTo("foo"); - - assertThat(testCase1.toString()).isEqualTo( - "DefaultTestCase[file=[moduleKey=foo, relative=src/Foo.php, abs=null],name=myTest,duration=1,status=ERROR,message=message,type=UNIT,stackTrace=stack]"); - assertThat(testCase1.hashCode()).isEqualTo(testCase1a.hashCode()); - } - -} -- cgit v1.2.3