This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-junit-healthcheck.git
commit 3472b089591ceb4466bcf2135ab7c01104b7b2b7 Author: Bertrand Delacretaz <[email protected]> AuthorDate: Tue Sep 24 21:22:21 2013 +0000 SLING-3108 - JUnit-based health checks git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1526015 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 115 ++++++++++++++ .../junit/healthcheck/impl/JUnitHealthCheck.java | 174 +++++++++++++++++++++ .../junit/healthcheck/impl/JUnitTestSelector.java | 52 ++++++ .../OSGI-INF/metatype/metatype.properties | 44 ++++++ .../healthcheck/impl/JUnitTestSelectorTest.java | 47 ++++++ 5 files changed, 432 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e988e81 --- /dev/null +++ b/pom.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>18</version> + <relativePath>../../../parent/pom.xml</relativePath> + </parent> + + <artifactId>org.apache.sling.junit.healthcheck</artifactId> + <version>0.0.9-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling JUnit Health Checks</name> + <description>Sling Health Check services that run JUnit tests</description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/testing/junit/remote</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/testing/junit/remote</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/testing/junit/remote</url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-scr-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package> + org.apache.sling.junit.remote.exported.*, + org.apache.sling.junit.remote.ide.* + </Export-Package> + <Import-Package> + org.apache.http.*; resolution:=optional, + org.apache.sling.testing.tools.http; resolution:=optional, + org.junit.internal.*; resolution:=optional, + * + </Import-Package> + <Sling-Test-Regexp>.*Test</Sling-Test-Regexp> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.junit.core</artifactId> + <version>1.0.8</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.2</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.5.11</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.5.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.hc.core</artifactId> + <version>0.0.2-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitHealthCheck.java b/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitHealthCheck.java new file mode 100644 index 0000000..ad1f2e9 --- /dev/null +++ b/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitHealthCheck.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The SF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.apache.sling.junit.healthcheck.impl; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.ConfigurationPolicy; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.PropertyUnbounded; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.hc.api.HealthCheck; +import org.apache.sling.hc.api.Result; +import org.apache.sling.hc.util.FormattingResultLog; +import org.apache.sling.junit.Renderer; +import org.apache.sling.junit.TestSelector; +import org.apache.sling.junit.TestsManager; +import org.junit.runner.Description; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** HealthCheck that executes JUnit tests */ +@Component( + configurationFactory=true, + policy=ConfigurationPolicy.REQUIRE, + metatype=true) +@Properties({ + @Property(name=HealthCheck.NAME), + @Property(name=HealthCheck.TAGS, unbounded=PropertyUnbounded.ARRAY), + @Property(name=HealthCheck.MBEAN_NAME) +}) +@Service(value=HealthCheck.class) +public class JUnitHealthCheck implements HealthCheck { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference + private TestsManager testsManager; + + @Property + public static final String TEST_PACKAGE_OR_CLASS_PROP = "test.package.or.class"; + private TestSelector testSelector; + + @Property + public static final String TEST_METHOD = "test.method"; + + private static class CustomRunListener extends RunListener { + + private final FormattingResultLog resultLog; + int nTests; + + CustomRunListener(FormattingResultLog resultLog) { + this.resultLog = resultLog; + } + + @Override + public void testFailure(Failure failure) throws Exception { + super.testFailure(failure); + resultLog.warn(failure.getMessage()); + } + + @Override + public void testFinished(Description description) throws Exception { + super.testFinished(description); + resultLog.debug("Test finished: {}", description); + nTests++; + } + } + + private static class CustomRenderer implements Renderer { + + private final String extension; + private final RunListener listener; + private final FormattingResultLog resultLog; + + CustomRenderer(RunListener listener, String extension, FormattingResultLog resultLog) { + this.extension = extension; + this.listener = listener; + this.resultLog = resultLog; + } + + public boolean appliesTo(TestSelector ts) { + return true; + } + + public void cleanup() { + } + + public String getExtension() { + return extension; + } + + public RunListener getRunListener() { + return listener; + } + + public void info(String role, String info) { + resultLog.info(info); + } + + public void link(String arg0, String arg1, String arg2) { + } + + public void list(String arg0, Collection<String> arg1) { + } + + public void setup(HttpServletResponse arg0, String arg1) throws IOException, UnsupportedEncodingException { + } + + public void title(int arg0, String arg1) { + } + } + + @Activate + public void activate(final Map<String, Object> properties) { + final String extension = "json"; + final Object o = properties.get(TEST_METHOD); + final String testMethod = o == null ? "" : o.toString(); + testSelector = new JUnitTestSelector( + String.valueOf(properties.get(TEST_PACKAGE_OR_CLASS_PROP)), + testMethod, + extension); + log.info("Activated with TestSelector={}", testSelector); + } + + public Result execute() { + final String extension ="json"; + final FormattingResultLog resultLog = new FormattingResultLog(); + final CustomRunListener listener = new CustomRunListener(resultLog); + final Renderer r = new CustomRenderer(listener, extension, resultLog); + final Collection<String> testNames = testsManager.getTestNames(testSelector); + if(testNames.isEmpty()) { + resultLog.warn("No tests found for selector {}", testSelector); + } else { + try { + testsManager.executeTests(testNames, r, testSelector); + if(listener.nTests == 0) { + resultLog.warn("No tests executed by {}", testSelector); + } + } catch(Exception e) { + resultLog.warn("Exception while executing tests (" + testSelector + ")" + e); + } + } + + return new Result(resultLog); + } + +} diff --git a/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelector.java b/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelector.java new file mode 100644 index 0000000..89540e7 --- /dev/null +++ b/src/main/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelector.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sling.junit.healthcheck.impl; + +import org.apache.sling.junit.TestSelector; + +class JUnitTestSelector implements TestSelector { + + private final String testPackageOrClass; + private final String testMethod; + private final String extension; + + JUnitTestSelector(String testPackageOrClass, String testMethod, String extension) { + this.testPackageOrClass = testPackageOrClass; + this.testMethod = testMethod; + this.extension = extension; + } + + public boolean acceptTestName(String name) { + return name.startsWith(testPackageOrClass); + } + + public String getExtension() { + return extension; + } + + public String getSelectedTestMethodName() { + return testMethod; + } + + public String getTestSelectorString() { + return testPackageOrClass + (testMethod == null ? "" : "#" + testMethod); + } + + public String toString() { + return getTestSelectorString(); + } +} diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties new file mode 100644 index 0000000..315b797 --- /dev/null +++ b/src/main/resources/OSGI-INF/metatype/metatype.properties @@ -0,0 +1,44 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# This file contains localization strings for configuration labels and +# descriptions as used in the metatype.xml descriptor generated by the +# the Sling SCR plugin + +org.apache.sling.junit.healthcheck.impl.name = JUnit Health Check +org.apache.sling.junit.healthcheck.impl.description = Health Check that executes JUnit tests + +hc.mbean.name.name = MBean name +hc.mbean.name.description = Name of the MBean to create for this Health Check. + +hc.tags.name = Health Check tags +hc.tags.description = List of tags for this Health Check service, used to select \ + subsets of Health Check services for execution. + +hc.name.name = Health Check Name +hc.name.description = Name of this Health Check service. Used for the MBean that's created \ + for this Health Check as well, unless a specific MBean name is configured. + +test.package.or.class.name = Test package or class +test.package.or.class.description = Package or class name to use to select which tests \ + to execute. + +test.method.name = Test method +test.method.description = Name of a specific test method to execute (optional). \ No newline at end of file diff --git a/src/test/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelectorTest.java b/src/test/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelectorTest.java new file mode 100644 index 0000000..c54ce89 --- /dev/null +++ b/src/test/java/org/apache/sling/junit/healthcheck/impl/JUnitTestSelectorTest.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sling.junit.healthcheck.impl; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +public class JUnitTestSelectorTest { + + @Test + public void testSelectorString() { + assertEquals("com.example.foo", new JUnitTestSelector("com.example.foo", null, null).getTestSelectorString()); + assertEquals("com.example.testing#someMethod", new JUnitTestSelector("com.example.testing", "someMethod", null).getTestSelectorString()); + } + + @Test + public void testNoMethod() { + final JUnitTestSelector s = new JUnitTestSelector("com.example.foo", null, null); + assertTrue("Expecting package to be selected", s.acceptTestName("com.example.foo")); + assertTrue("Expecting subpackage to be selected", s.acceptTestName("com.example.foo.bar")); + assertTrue("Expecting class to be selected", s.acceptTestName("com.example.foo.some.ThisClass")); + assertFalse("Expecting other package.accept to return false", s.acceptTestName("com.other.foo")); + } + + @Test + public void testWithMethod() { + final JUnitTestSelector s = new JUnitTestSelector("com.example.foo", "someMethod", null); + assertTrue("Expecting package to be selected", s.acceptTestName("com.example.foo")); + assertEquals("someMethod", s.getSelectedTestMethodName()); + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
