diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2013-02-05 19:07:42 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2013-02-05 19:10:17 +0100 |
commit | b58601cce773c23cdef9feb56e0cc486f000001a (patch) | |
tree | 1acd3da6c4cdaabb0e7375f5613beb3da418e079 | |
parent | f0e662a2b73e0e9ae70b005e7093c5c27fab24d8 (diff) | |
download | sonarqube-b58601cce773c23cdef9feb56e0cc486f000001a.tar.gz sonarqube-b58601cce773c23cdef9feb56e0cc486f000001a.zip |
SONAR-2501 a test plan can have multiple test cases with the same name (see TestNG)
17 files changed, 143 insertions, 111 deletions
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/web/tests_viewer.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/web/tests_viewer.html.erb index 122fd22b7cc..47f5aac6a91 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/web/tests_viewer.html.erb +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/web/tests_viewer.html.erb @@ -52,16 +52,16 @@ end else # New Test API - test_plan = controller.java_facade.getTestPlan(@snapshot.id) + test_plan = controller.java_facade.testPlan(@snapshot.id) if test_plan test_plan.testCases().each do |test| test_case = {} test_case[:name] = test.name() - test_case[:status] = test.status() + test_case[:status] = test.status().to_s test_case[:time] = test.durationInMs() has_covered_lines = test.doesCover() test_case[:covered_lines] = test.countCoveredLines() if has_covered_lines - if test.status() != 'ok' + if test.status().to_s != 'ok' test_case[:message] = '' test_case[:message] = test.message() if test.message() test_case[:stack_trace] = html_escape(test.stackTrace()) diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml index 02576867e15..7c733839da0 100644 --- a/sonar-application/pom.xml +++ b/sonar-application/pom.xml @@ -210,7 +210,7 @@ <configuration> <rules> <requireFilesSize> - <maxsize>54000000</maxsize> + <maxsize>55000000</maxsize> <minsize>52000000</minsize> <files> <file>${project.build.directory}/sonar-${project.version}.zip</file> diff --git a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestCase.java b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestCase.java index d7b200e4673..7b535ad7c23 100644 --- a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestCase.java +++ b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestCase.java @@ -50,24 +50,12 @@ public class DefaultTestCase extends BeanVertex implements MutableTestCase { return this; } - public String status() { - return (String) getProperty("status"); + public Status status() { + return Status.of((String)getProperty("status")); } - public MutableTestCase setStatus(@Nullable String s) { - setProperty("status", s); - return this; - } - - /** - * The key is not blank and unique among the test plan. - */ - public String key() { - return (String) getProperty("key"); - } - - public MutableTestCase setKey(String s) { - setProperty("key", s); + public MutableTestCase setStatus(@Nullable Status s) { + setProperty("status", s == null ? null : s.toString()); return this; } diff --git a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestPlan.java b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestPlan.java index c1947f9b168..a9c4b69cc02 100644 --- a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestPlan.java +++ b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestPlan.java @@ -19,10 +19,10 @@ */ package org.sonar.core.test; +import com.google.common.collect.Lists; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Vertex; import org.sonar.api.component.Component; -import org.sonar.api.test.exception.TestCaseAlreadyExistsException; import org.sonar.api.test.MutableTestCase; import org.sonar.api.test.MutableTestPlan; import org.sonar.core.component.ComponentVertex; @@ -31,6 +31,8 @@ import org.sonar.core.graph.GraphUtil; import javax.annotation.CheckForNull; +import java.util.List; + public class DefaultTestPlan extends BeanVertex implements MutableTestPlan { public Component component() { Vertex component = GraphUtil.singleAdjacent(element(), Direction.IN, "testplan"); @@ -47,21 +49,19 @@ public class DefaultTestPlan extends BeanVertex implements MutableTestPlan { } @CheckForNull - public MutableTestCase testCaseByKey(String key) { + public Iterable<MutableTestCase> testCasesByName(String name) { + List<MutableTestCase> result = Lists.newArrayList(); for (MutableTestCase testCase : testCases()) { - if (key.equals(testCase.key())) { - return testCase; + if (name.equals(testCase.name())) { + result.add(testCase); } } - return null; + return result; } - public MutableTestCase addTestCase(String key) { - if (testCaseByKey(key)!=null) { - throw new TestCaseAlreadyExistsException(component().key(), key); - } + public MutableTestCase addTestCase(String name) { DefaultTestCase testCase = beanGraph().createAdjacentVertex(this, DefaultTestCase.class, "testcase"); - testCase.setKey(key); + testCase.setName(name); return testCase; } diff --git a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java index 25a3510f162..a3b4f2598c4 100644 --- a/sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java +++ b/sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java @@ -53,10 +53,10 @@ public class DefaultTestable extends BeanVertex implements MutableTestable { return cases.build(); } - public TestCase testCaseByKey(final String key) { + public TestCase testCaseByName(final String name) { return Iterables.find(testCases(), new Predicate<TestCase>() { public boolean apply(TestCase input) { - return input.key().equals(key); + return input.name().equals(name); } }, null); } @@ -94,7 +94,7 @@ public class DefaultTestable extends BeanVertex implements MutableTestable { public Cover coverOfTestCase(final TestCase testCase) { return Iterables.find(getEdges(DefaultCover.class, Direction.IN, "covers"), new Predicate<Cover>() { public boolean apply(Cover input) { - return input.testCase().key().equals(testCase.key()); + return input.testCase().name().equals(testCase.name()); } }, null); } diff --git a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestCaseTest.java b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestCaseTest.java index 212216dcf5d..8dc9289bc9d 100644 --- a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestCaseTest.java +++ b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestCaseTest.java @@ -83,7 +83,7 @@ public class DefaultTestCaseTest { } @Test - public void should_return_cover_of_testable(){ + public void should_return_cover_of_testable() { BeanGraph beanGraph = BeanGraph.createInMemory(); ScanGraph graph = ScanGraph.create(); @@ -106,19 +106,17 @@ public class DefaultTestCaseTest { BeanGraph beanGraph = BeanGraph.createInMemory(); DefaultTestCase testCase = beanGraph.createVertex(DefaultTestCase.class); - testCase.setKey("T1") - .setName("Test one") + testCase.setName("T1") .setDurationInMs(1234L) .setMessage("Error msg") .setStackTrace("xxx") - .setStatus(TestCase.STATUS_FAIL); + .setStatus(TestCase.Status.ERROR); - assertThat(testCase.key()).isEqualTo("T1"); - assertThat(testCase.name()).isEqualTo("Test one"); + assertThat(testCase.name()).isEqualTo("T1"); assertThat(testCase.message()).isEqualTo("Error msg"); assertThat(testCase.stackTrace()).isEqualTo("xxx"); assertThat(testCase.durationInMs()).isEqualTo(1234L); - assertThat(testCase.status()).isEqualTo(TestCase.STATUS_FAIL); + assertThat(testCase.status()).isEqualTo(TestCase.Status.ERROR); } @Test diff --git a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestPlanTest.java b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestPlanTest.java index 32a3c32157e..816bdb13d4c 100644 --- a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestPlanTest.java +++ b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestPlanTest.java @@ -23,10 +23,8 @@ import com.google.common.collect.Iterables; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.test.exception.TestCaseAlreadyExistsException; import org.sonar.api.test.MutableTestCase; import org.sonar.api.test.TestPlan; -import org.sonar.core.component.ComponentVertex; import org.sonar.core.graph.BeanGraph; import static org.fest.assertions.Assertions.assertThat; @@ -53,46 +51,46 @@ public class DefaultTestPlanTest { assertThat(plan.testCases()).hasSize(2); MutableTestCase firstTestCase = Iterables.get(plan.testCases(), 0); - assertThat(firstTestCase.key()).isEqualTo("T1"); + assertThat(firstTestCase.name()).isEqualTo("T1"); assertThat(firstTestCase.testPlan()).isSameAs(plan); MutableTestCase secondTestCase = Iterables.get(plan.testCases(), 1); - assertThat(secondTestCase.key()).isEqualTo("T2"); + assertThat(secondTestCase.name()).isEqualTo("T2"); assertThat(secondTestCase.testPlan()).isSameAs(plan); } @Test - public void should_find_test_case_by_key() { + public void should_find_test_case_by_name() { BeanGraph beanGraph = BeanGraph.createInMemory(); DefaultTestPlan plan = beanGraph.createVertex(DefaultTestPlan.class); plan.addTestCase("T1"); plan.addTestCase("T2"); - assertThat(plan.testCaseByKey("T1").key()).isEqualTo("T1"); - assertThat(plan.testCaseByKey("T3")).isNull(); + assertThat(plan.testCasesByName("T1")).hasSize(1); + assertThat(Iterables.get(plan.testCasesByName("T1"), 0).name()).isEqualTo("T1"); + assertThat(plan.testCasesByName("T3")).isEmpty(); } @Test - public void should_set_type() { + public void should_find_multiple_test_cases_by_name() { BeanGraph beanGraph = BeanGraph.createInMemory(); DefaultTestPlan plan = beanGraph.createVertex(DefaultTestPlan.class); - assertThat(plan.type()).isNull(); + plan.addTestCase("T1"); + plan.addTestCase("T1"); - plan.setType(TestPlan.TYPE_UNIT); - assertThat(plan.type()).isEqualTo(TestPlan.TYPE_UNIT); + assertThat(plan.testCasesByName("T1")).hasSize(2); } @Test - public void keys_of_test_cases_should_be_unique() { - thrown.expect(TestCaseAlreadyExistsException.class); - + public void should_set_type() { BeanGraph beanGraph = BeanGraph.createInMemory(); - ComponentVertex component = beanGraph.createVertex(ComponentVertex.class); - DefaultTestPlan plan = beanGraph.createAdjacentVertex(component, DefaultTestPlan.class, "testplan"); - plan.addTestCase("T1"); - plan.addTestCase("T1"); + DefaultTestPlan plan = beanGraph.createVertex(DefaultTestPlan.class); + assertThat(plan.type()).isNull(); + + plan.setType(TestPlan.TYPE_UNIT); + assertThat(plan.type()).isEqualTo(TestPlan.TYPE_UNIT); } } diff --git a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java index 3a921a2508d..cbf107b1617 100644 --- a/sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java +++ b/sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java @@ -86,9 +86,9 @@ public class DefaultTestableTest { MutableTestCase testCase2 = Iterables.get(plan.testCases(), 1); testCase2.setCover(testable, Arrays.asList(12, 48, 49)); - assertThat(testable.testCaseByKey("T1")).isEqualTo(testCase1); - assertThat(testable.testCaseByKey("T2")).isEqualTo(testCase2); - assertThat(testable.testCaseByKey("Unknown")).isNull(); + assertThat(testable.testCaseByName("T1")).isEqualTo(testCase1); + assertThat(testable.testCaseByName("T2")).isEqualTo(testCase2); + assertThat(testable.testCaseByName("Unknown")).isNull(); } @Test diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java index ee258383d9f..a65b652750a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java @@ -24,12 +24,10 @@ import javax.annotation.Nullable; import java.util.List; public interface MutableTestCase extends TestCase { - MutableTestCase setStatus(String s); + MutableTestCase setStatus(Status s); MutableTestCase setDurationInMs(@Nullable Long l); - MutableTestCase setName(String s); - MutableTestCase setMessage(String s); MutableTestCase setStackTrace(String s); 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 168b07ad189..5b89bbb7fda 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 @@ -19,22 +19,23 @@ */ package org.sonar.api.test; +import javax.annotation.Nullable; + public interface TestCase { - String STATUS_PASS = "pass"; - String STATUS_FAIL = "fail"; + enum Status { + OK, FAILURE, ERROR, SKIPPED; + + public static Status of(@Nullable String s) { + return s == null ? null : valueOf(s.toUpperCase()); + } + } /** * Duration in milliseconds */ Long durationInMs(); - // pass/fail/... - String status(); - - /** - * The key is not null and unique among the test plan. - */ - String key(); + Status status(); String name(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java index 1c334e2442b..1b1bb914cb9 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java @@ -32,5 +32,5 @@ public interface TestPlan<T extends TestCase> extends Perspective { Iterable<T> testCases(); - T testCaseByKey(String key); + Iterable<T> testCasesByName(String name); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java index f11a3a5fef8..77ec933b522 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java @@ -28,7 +28,7 @@ public interface Testable extends Perspective { List<TestCase> testCases(); - TestCase testCaseByKey(String key); + TestCase testCaseByName(String key); int countTestCasesOfLine(Integer line); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/exception/TestCaseAlreadyExistsException.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/exception/TestCaseAlreadyExistsException.java deleted file mode 100644 index ff1453b9ba8..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/exception/TestCaseAlreadyExistsException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.api.test.exception; - -public class TestCaseAlreadyExistsException extends TestException { - public TestCaseAlreadyExistsException(String componentKey, String testCaseKey) { - super(String.format("Test case already exists for %s: %s", componentKey, testCaseKey)); - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index 5127fe218a8..082e08fb34f 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -325,7 +325,7 @@ public final class JRubyFacade { public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) { getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId], - RulePriority.values()[newSeverityId], userName); + RulePriority.values()[newSeverityId], userName); } public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) { @@ -521,10 +521,10 @@ public final class JRubyFacade { // notifier is null when creating the administrator in the migration script 011. if (notifier != null) { notifier.onNewUser(NewUserHandler.Context.builder() - .setLogin(fields.get("login")) - .setName(fields.get("name")) - .setEmail(fields.get("email")) - .build()); + .setLogin(fields.get("login")) + .setName(fields.get("name")) + .setEmail(fields.get("email")) + .build()); } } @@ -544,11 +544,15 @@ public final class JRubyFacade { return get(Periods.class).abbreviation(periodIndex); } - public TestPlan getTestPlan(long snapshotId) { + public TestPlan testPlan(long snapshotId) { return get(SnapshotPerspectives.class).as(MutableTestPlan.class, snapshotId); } - public Testable getTestable(long snapshotId) { + public TestPlan testPlan(String componentKey) { + return get(SnapshotPerspectives.class).as(MutableTestPlan.class, componentKey); + } + + public Testable testable(long snapshotId) { return get(SnapshotPerspectives.class).as(MutableTestable.class, snapshotId); } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/tests_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/tests_controller.rb new file mode 100644 index 00000000000..8c2eda47153 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/tests_controller.rb @@ -0,0 +1,71 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar 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. +# +# Sonar 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 Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# +class Api::TestsController < Api::ApiController + + # GET /api/tests/plan?resource=<test file id or key> + # + # Get the details of a given test plan : + # - test cases + # - resources covered by test cases + # + # Since v.3.5 + # + # ==== Examples + # - get the test plan defined by the file com/mycompany/FooTest.c of my_project : GET /api/tests/plan?resource=my_project:com/mycompany/FooTest.c + # + def plan + require_parameters :resource + + resource=Project.by_key(params[:resource]) + not_found("Not found: #{params[:resource]}") unless resource + access_denied unless has_role?(:user, resource) + + plan = java_facade.testPlan(resource.key) + json = {} + if plan + json[:type] = plan.type + json[:test_cases] = plan.testCases.map do |test_case| + test_case_json = {:name => test_case.name} + test_case_json[:message] = test_case.message if test_case.message + test_case_json[:durationInMs] = test_case.durationInMs if test_case.durationInMs + test_case_json[:status] = test_case.status.to_s if test_case.status + test_case_json[:stackTrace] = test_case.stackTrace if test_case.stackTrace + if test_case.doesCover() + test_case_json[:covers] = test_case.covers.map do |cover| + cover_json = {} + resource = cover.testable.component + cover_json[:resourceKey] = resource.key + cover_json[:resourceName] = resource.name + cover_json[:resourceQualifier] = resource.qualifier + cover_json[:lines] = cover.lines + cover_json + end + end + test_case_json + end + + respond_to do |format| + format.json { render :json => jsonp(json) } + format.xml { render :xml => xml_not_supported } + format.text { render :text => text_not_supported } + end + end + end +end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index cd18218585d..4fb0999f00f 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -205,7 +205,7 @@ class ResourceController < ApplicationController @conditions_by_line = load_distribution("#{it_prefix}conditions_by_line") @covered_conditions_by_line = load_distribution("#{it_prefix}covered_conditions_by_line") - @testable = java_facade.getTestable(@snapshot.id) + @testable = java_facade.testable(@snapshot.id) @hits_by_line.each_pair do |line_id, hits| line = @lines[line_id-1] if line diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/test_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/test_controller.rb index dfb93c79808..13bdc012ec7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/test_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/test_controller.rb @@ -25,7 +25,7 @@ class TestController < ApplicationController snapshot_id = params[:sid].to_i @test = params[:test].to_s - @test_plan = java_facade.getTestPlan(snapshot_id) + @test_plan = java_facade.testPlan(snapshot_id) @test_case = @test_plan.testCaseByKey(@test) render :partial => 'test/testcase_working_view' end @@ -36,7 +36,7 @@ class TestController < ApplicationController snapshot_id = params[:sid].to_i @line = params[:line].to_i - @testable = java_facade.getTestable(snapshot_id) + @testable = java_facade.testable(snapshot_id) @test_case_by_test_plan = {} @testable.testCasesOfLine(@line).each do |test_case| test_plan = test_case.testPlan |