mirror of
https://github.com/Alfresco/alfresco-sdk.git
synced 2025-07-31 17:39:14 +00:00
Initial check-in of Bindu's AlfrescoTestRunner frameowork plus sample tests, #401
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Rapid Application Development Support</name>
|
||||
<description>SDK module for Rapid Development support</description>
|
||||
<description>SDK module for Rapid Development support, such as Alfresco JUnit runner</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.alfresco.maven</groupId>
|
||||
<artifactId>alfresco-sdk-aggregator</artifactId>
|
||||
@@ -13,116 +14,29 @@
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<pgsql.dialect.folder>${project.build.directory}/pg-dialect-tmp</pgsql.dialect.folder>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Enables JUnit remote testing (using JRebel) -->
|
||||
<dependency>
|
||||
<groupId>com.tradeshift</groupId>
|
||||
<artifactId>junit-remote</artifactId>
|
||||
<version>3</version>
|
||||
<type>jar</type>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Required to have annotation based remote testing working -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.0.6.RELEASE</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Copied PostgreSQL dialect files to generate H2 dialect files on-the-fly -->
|
||||
<!--
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>extract-postgres-dialect</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-repository</artifactId>
|
||||
<version>${alfresco.community.default.version}</version>
|
||||
<includes>alfresco/dbscripts/create/org.hibernate.dialect.PostgreSQLDialect/*,alfresco/dbscripts/upgrade/*/org.hibernate.dialect.PostgreSQLDialect/*,alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect/*</includes>
|
||||
<outputDirectory>${pgsql.dialect.folder}</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-h2-dialect</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/create/org.hibernate.dialect.PostgreSQLDialect</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
<targetPath>alfresco/dbscripts/create/org.hibernate.dialect.H2Dialect</targetPath>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${pgsql.dialect.folder}/alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
<targetPath>alfresco/ibatis/org.hibernate.dialect.H2Dialect</targetPath>
|
||||
</resource>
|
||||
Upgrade scripts - does not seem to be picked up, so any changes you would make to them are not picked up...
|
||||
<resource>
|
||||
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.PostgreSQLDialect</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
<targetPath>alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.H2Dialect</targetPath>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/4.2/org.hibernate.dialect.PostgreSQLDialect</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
<targetPath>alfresco/dbscripts/upgrade/4.2/org.hibernate.dialect.H2Dialect</targetPath>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/5.0/org.hibernate.dialect.PostgreSQLDialect</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
<targetPath>alfresco/dbscripts/upgrade/5.0/org.hibernate.dialect.H2Dialect</targetPath>
|
||||
</resource>
|
||||
<!-- Access to org.alfresco.service.ServiceRegistry -->
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-repository</artifactId>
|
||||
<version>${alfresco.community.default.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
<!-- Bring in ApplicationContextAware, ApplicationContext etc -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.17.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Access to JUnit runner classes -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -1,16 +0,0 @@
|
||||
package org.alfresco.maven.rad;
|
||||
|
||||
import com.tradeshift.test.remote.RemoteServer;
|
||||
|
||||
public class RemoteRunnerWrapper implements Runnable {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
RemoteServer.main(new String []{});
|
||||
} catch (Exception e) {
|
||||
System.out.println("Could not start JUnit remoteServer because of: " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Alfresco Software Limited.
|
||||
* <p/>
|
||||
* This file is part of the Alfresco SDK project.
|
||||
* <p/>
|
||||
* Licensed 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.alfresco.rad;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* This Spring bean is aware of the application context in which
|
||||
* it is initialized.
|
||||
*
|
||||
* @author martin.bergljung@alfresco.com
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SpringContextHolder implements ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* The instance of SpringContextHolder
|
||||
*/
|
||||
private static SpringContextHolder springContextHolderInstance;
|
||||
|
||||
/**
|
||||
* The Alfresco Spring Application Context.
|
||||
*/
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SpringContextHolder() {
|
||||
System.out.println("Initializing the SpringContextHolder class.");
|
||||
springContextHolderInstance = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static SpringContextHolder Instance() {
|
||||
return springContextHolderInstance;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
System.out.println("Setting current Spring Application Context in SpringContextHolder class.");
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Alfresco Software Limited.
|
||||
* <p/>
|
||||
* This file is part of the Alfresco SDK project.
|
||||
* <p/>
|
||||
* Licensed 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.alfresco.rad.test;
|
||||
|
||||
import org.alfresco.rad.SpringContextHolder;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.MethodRule;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Abstract Integration Test class to be used
|
||||
* by Alfresco Integration Tests. Gives access to
|
||||
* Alfresco Spring Application context and the
|
||||
* {@link ServiceRegistry} that should be used when
|
||||
* accessing Alfresco Services.
|
||||
*
|
||||
* @author martin.bergljung@alfresco.com
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractAlfrescoIT {
|
||||
private ApplicationContext applicationContext = null;
|
||||
private ServiceRegistry serviceRegistry = null;
|
||||
|
||||
/**
|
||||
* Print the test we are currently running, useful if the test is running remotely
|
||||
* and we don't see the server logs
|
||||
*/
|
||||
@Rule
|
||||
public MethodRule testAnnouncer = new MethodRule() {
|
||||
@Override
|
||||
public Statement apply(Statement base, FrameworkMethod method, Object target) {
|
||||
System.out.println("Running " + getClassName() + " Integration Test: " + method.getName() + "()");
|
||||
return base;
|
||||
}
|
||||
};
|
||||
|
||||
protected String getClassName() {
|
||||
Class<?> enclosingClass = getClass().getEnclosingClass();
|
||||
if (enclosingClass != null) {
|
||||
return enclosingClass.getName();
|
||||
} else {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
if (applicationContext == null) {
|
||||
SpringContextHolder springContextHolder = SpringContextHolder.Instance();
|
||||
if (springContextHolder != null) {
|
||||
applicationContext = springContextHolder.getApplicationContext();
|
||||
}
|
||||
}
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
protected ServiceRegistry getServiceRegistry() {
|
||||
if (serviceRegistry == null) {
|
||||
ApplicationContext ctx = getApplicationContext();
|
||||
if (ctx != null) {
|
||||
Object bean = ctx.getBean("ServiceRegistry");
|
||||
if (bean != null && bean instanceof ServiceRegistry) {
|
||||
serviceRegistry = (ServiceRegistry) bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serviceRegistry;
|
||||
}
|
||||
}
|
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Alfresco Software Limited.
|
||||
* <p/>
|
||||
* This file is part of the Alfresco SDK project.
|
||||
* <p/>
|
||||
* Licensed 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.alfresco.rad.test;
|
||||
|
||||
import org.alfresco.rad.SpringContextHolder;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This is a JUnit test runner that is designed to work with an Alfresco repository.
|
||||
* It detects if it's executing a test inside of a running Alfresco instance. If that
|
||||
* is the case the tests are all run normally. If however the test is being run from
|
||||
* outside the repository, from the maven command line or from an IDE
|
||||
* such as IntelliJ or STS/Eclipse for example, then instead of running the actual
|
||||
* test an HTTP request is made to a Web Script in a running Alfresco instance. This
|
||||
* Web Script runs the test and returns enough information to this class so we can
|
||||
* emulate having run the test locally.
|
||||
* <p/>
|
||||
* By doing this, we are able to create Integration Tests (IT) using standard JUnit
|
||||
* capabilities. These can then be run from our IDEs with the associated visualizations,
|
||||
* support for re-running failed tests, etc.
|
||||
* <p/>
|
||||
* Integration testing framework donated by Zia Consulting
|
||||
*
|
||||
* @author Bindu Wavell <bindu@ziaconsulting.com>
|
||||
* @author martin.bergljung@alfresco.com (some editing)
|
||||
* @since 3.0
|
||||
*/
|
||||
public class AlfrescoTestRunner extends BlockJUnit4ClassRunner {
|
||||
public static final String SUCCESS = "SUCCESS";
|
||||
public static final String FAILURE = "FAILURE";
|
||||
|
||||
public AlfrescoTestRunner(Class<?> klass) throws InitializationError {
|
||||
super(klass);
|
||||
}
|
||||
|
||||
public static String serializableToString(Serializable serializable) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(serializable);
|
||||
oos.close();
|
||||
|
||||
String string = Base64.encodeBase64URLSafeString(baos.toByteArray());
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
|
||||
if (areWeRunningInAlfresco()) {
|
||||
// Just run the test as normally
|
||||
super.runChild(method, notifier);
|
||||
} else {
|
||||
// We are not running in an Alfresco Server, we need to call one and have it execute the test...
|
||||
Description desc = describeChild(method);
|
||||
if (method.getAnnotation(Ignore.class) != null) {
|
||||
notifier.fireTestIgnored(desc);
|
||||
} else {
|
||||
callProxiedChild(method, notifier, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a remote Alfresco server and have the test run there.
|
||||
*
|
||||
* @param method the test method to run
|
||||
* @param notifier
|
||||
* @param desc
|
||||
*/
|
||||
protected void callProxiedChild(FrameworkMethod method, RunNotifier notifier, Description desc) {
|
||||
notifier.fireTestStarted(desc);
|
||||
|
||||
String className = method.getMethod().getDeclaringClass().getCanonicalName();
|
||||
String methodName = method.getName();
|
||||
if (null != methodName) {
|
||||
className += "#" + methodName;
|
||||
}
|
||||
|
||||
// Login credentials for Alfresco Repo
|
||||
// TODO: Maybe configure credentials in props...
|
||||
CredentialsProvider provider = new BasicCredentialsProvider();
|
||||
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin");
|
||||
provider.setCredentials(AuthScope.ANY, credentials);
|
||||
|
||||
// Create HTTP Client with credentials
|
||||
CloseableHttpClient httpclient = HttpClientBuilder.create()
|
||||
.setDefaultCredentialsProvider(provider)
|
||||
.build();
|
||||
|
||||
// Create the GET Request for the Web Script that will run the test
|
||||
String testWebScriptUrl = "/service/testing/test.xml?clazz=" + className.replace("#", "%23");
|
||||
System.out.println("AlfrescoTestRunner: Invoking Web Script for test execution: " + testWebScriptUrl);
|
||||
HttpGet get = new HttpGet(getContextRoot(method) + testWebScriptUrl);
|
||||
|
||||
try {
|
||||
// Send proxied request and read response
|
||||
HttpResponse resp = httpclient.execute(get);
|
||||
InputStream is = resp.getEntity().getContent();
|
||||
InputStreamReader ir = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(ir);
|
||||
String body = "";
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
body += line + "\n";
|
||||
}
|
||||
|
||||
// Process response
|
||||
if (body.length() > 0) {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = null;
|
||||
dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(new InputSource(new StringReader(body)));
|
||||
|
||||
Element root = doc.getDocumentElement();
|
||||
NodeList results = root.getElementsByTagName("result");
|
||||
if (null != results && results.getLength() > 0) {
|
||||
String result = results.item(0).getFirstChild().getNodeValue();
|
||||
if (SUCCESS.equals(result)) {
|
||||
notifier.fireTestFinished(desc);
|
||||
} else {
|
||||
boolean failureFired = false;
|
||||
NodeList throwableNodes = root.getElementsByTagName("throwable");
|
||||
for (int tid = 0; tid < throwableNodes.getLength(); tid++) {
|
||||
String throwableBody = null;
|
||||
Object object = null;
|
||||
Throwable throwable = null;
|
||||
throwableBody = throwableNodes.item(tid).getFirstChild().getNodeValue();
|
||||
if (null != throwableBody) {
|
||||
try {
|
||||
object = objectFromString(throwableBody);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
if (null != object && object instanceof Throwable) {
|
||||
throwable = (Throwable) object;
|
||||
}
|
||||
}
|
||||
if (null == throwable) {
|
||||
throwable = new Throwable("Unable to process exception body: " + throwableBody);
|
||||
}
|
||||
|
||||
notifier.fireTestFailure(new Failure(desc, throwable));
|
||||
failureFired = true;
|
||||
}
|
||||
if (!failureFired) {
|
||||
notifier.fireTestFailure(new Failure(desc, new Throwable(
|
||||
"There was an error but we can't figure out what it was, sorry!")));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifier.fireTestFailure(new Failure(desc, new Throwable(
|
||||
"Unable to process response for proxied test request: " + body)));
|
||||
}
|
||||
} else {
|
||||
notifier.fireTestFailure(new Failure(desc, new Throwable(
|
||||
"Attempt to proxy test into running Alfresco instance failed, no response received")));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
notifier.fireTestFailure(new Failure(desc, e));
|
||||
} catch (ParserConfigurationException e) {
|
||||
notifier.fireTestFailure(new Failure(desc, e));
|
||||
} catch (SAXException e) {
|
||||
notifier.fireTestFailure(new Failure(desc, e));
|
||||
} finally {
|
||||
try {
|
||||
httpclient.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static Object objectFromString(String string) throws IOException, ClassNotFoundException {
|
||||
byte[] buffer = Base64.decodeBase64(string);
|
||||
ObjectInputStream ois = new ObjectInputStream(
|
||||
new ByteArrayInputStream(buffer));
|
||||
Object object = ois.readObject();
|
||||
ois.close();
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are running this test in an Alfresco server instance.
|
||||
*
|
||||
* @return true if we are running in an Alfresco server
|
||||
*/
|
||||
protected boolean areWeRunningInAlfresco() {
|
||||
Object contextHolder = SpringContextHolder.Instance();
|
||||
return (contextHolder != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the @Remote config on the test class to see where the
|
||||
* Alfresco Repo is running
|
||||
*
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
protected String getContextRoot(FrameworkMethod method) {
|
||||
Class<?> declaringClass = method.getMethod().getDeclaringClass();
|
||||
boolean annotationPresent = declaringClass.isAnnotationPresent(Remote.class);
|
||||
if (annotationPresent) {
|
||||
Remote annotation = declaringClass.getAnnotation(Remote.class);
|
||||
return annotation.endpoint();
|
||||
}
|
||||
|
||||
return "http://localhost:8080/alfresco";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Alfresco Software Limited.
|
||||
* <p/>
|
||||
* This file is part of the Alfresco SDK project.
|
||||
* <p/>
|
||||
* Licensed 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.alfresco.rad.test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* By default the ${@link AlfrescoTestRunner} will attempt to find a
|
||||
* running Alfresco instance at http://localhost:8080/alfresco
|
||||
* This annotation can be applied to a test class to have the
|
||||
* proxy calls go to a different host/port.
|
||||
* <p/>
|
||||
* Integration testing framework donated by Zia Consulting.
|
||||
*
|
||||
* @author Bindu Wavell <bindu@ziaconsulting.com>
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Remote {
|
||||
|
||||
String endpoint() default "http://localhost:8080/alfresco";
|
||||
|
||||
}
|
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Alfresco Software Limited.
|
||||
* <p/>
|
||||
* This file is part of the Alfresco SDK project.
|
||||
* <p/>
|
||||
* Licensed 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.alfresco.rad.test;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.junit.runner.JUnitCore;
|
||||
import org.junit.runner.Request;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This Web Script works in consort with the ${@link AlfrescoTestRunner}. When a test is run from an IDE or
|
||||
* command line, the Alfresco test runner sends a proxied request to perform the test to this script. This runs
|
||||
* the test and wraps the results up so that the test initiator can be fooled into thinking they are
|
||||
* running the tests locally.
|
||||
* <p/>
|
||||
* Integration testing framework donated by Zia Consulting.
|
||||
*
|
||||
* @author Bindu Wavell <bindu@ziaconsulting.com>
|
||||
* @author martin.bergljung@alfresco.com (some editing)
|
||||
* @since 3.0
|
||||
*/
|
||||
public class RunTestWebScript extends DeclarativeWebScript {
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
|
||||
System.out.println("RunTestWebScript: Start executing ...");
|
||||
String result = AlfrescoTestRunner.FAILURE;
|
||||
String clazzAndMethod = null;
|
||||
String clazz = null; // Test class
|
||||
String method = null; // Test method
|
||||
Result junitRunnerResult = null;
|
||||
|
||||
// Example invocation:
|
||||
// /service/testing/test.xml?clazz=org.alfresco.test.platformsample.DemoComponentIT%23testChildNodesCount
|
||||
|
||||
// First, try and get the test class, including method, from a template var, i.e. /clazz/{class%23method}
|
||||
clazzAndMethod = req.getServiceMatch().getTemplateVars().get("clazz");
|
||||
if (clazzAndMethod == null) {
|
||||
// Not found in template var, try parameter, i.e. ?clazz={class%23method}
|
||||
clazzAndMethod = req.getParameter("clazz");
|
||||
}
|
||||
System.out.println("RunTestWebScript: clazzAndMethod = " + clazzAndMethod);
|
||||
|
||||
// Do we have a test class and method now?
|
||||
if (clazzAndMethod == null) {
|
||||
// No, set class and method as not provided
|
||||
clazzAndMethod = "not provided";
|
||||
} else {
|
||||
// We got a test class and method, proceed
|
||||
Class c = null;
|
||||
// Split class and method on %23 = #
|
||||
String[] clazzAndMethodArray = clazzAndMethod.split("#");
|
||||
if (clazzAndMethodArray.length > 1) {
|
||||
clazz = clazzAndMethodArray[0];
|
||||
method = clazzAndMethodArray[1];
|
||||
}
|
||||
System.out.println("RunTestWebScript: [clazz=" + clazz + "][method=" + method + "]");
|
||||
|
||||
try {
|
||||
// Load the Java class that will be run by JUnit
|
||||
c = Class.forName(clazz);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new AlfrescoRuntimeException("Could not find test class: " + clazzAndMethod);
|
||||
}
|
||||
|
||||
// See if JUnit should run test for whole class, or just specified method
|
||||
if (method == null) {
|
||||
// No method, run all tests in class
|
||||
junitRunnerResult = JUnitCore.runClasses(c);
|
||||
} else {
|
||||
// We got one specific test method to run
|
||||
Request jreq = Request.method(c, method);
|
||||
junitRunnerResult = new JUnitCore().run(jreq);
|
||||
}
|
||||
|
||||
// Check if test was successful
|
||||
if (junitRunnerResult.wasSuccessful()) {
|
||||
result = AlfrescoTestRunner.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up model to send to Web Script template
|
||||
//
|
||||
// What test did we run
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
if (method == null) {
|
||||
// We don't have a test method...
|
||||
model.put("test", clazzAndMethod);
|
||||
} else {
|
||||
model.put("test", clazzAndMethod + "#" + method);
|
||||
}
|
||||
// Overall Alfresco Test runner result
|
||||
model.put("result", result);
|
||||
// JUnit Runner stats
|
||||
if (junitRunnerResult != null) {
|
||||
model.put("resultObject", junitRunnerResult);
|
||||
model.put("failures", junitRunnerResult.getFailures());
|
||||
model.put("failureCount", junitRunnerResult.getFailureCount());
|
||||
model.put("ignoreCount", junitRunnerResult.getIgnoreCount());
|
||||
model.put("runCount", junitRunnerResult.getRunCount());
|
||||
model.put("runTime", junitRunnerResult.getRunTime());
|
||||
List<String> throwables = new ArrayList<>();
|
||||
if (null != junitRunnerResult.getFailures()) {
|
||||
for (Failure failure : junitRunnerResult.getFailures()) {
|
||||
try {
|
||||
throwables.add(AlfrescoTestRunner.serializableToString(failure.getException()));
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
throwables.add(AlfrescoTestRunner.serializableToString(
|
||||
"Unable to serialize exception."));
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.put("throwables", throwables);
|
||||
model.put("wasSuccessful", junitRunnerResult.wasSuccessful());
|
||||
}
|
||||
|
||||
System.out.println("RunTestWebScript: model = " + model);
|
||||
System.out.println("RunTestWebScript: Stopped executing");
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -1,29 +1,33 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements.
|
||||
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.
|
||||
|
||||
-->
|
||||
Copyright (C) 2017 Alfresco Software Limited.
|
||||
|
||||
This file is part of the Alfresco SDK project.
|
||||
|
||||
Licensed 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.
|
||||
-->
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="remoteRunnnerWrapper" class="org.alfresco.maven.rad.RemoteRunnerWrapper"/>
|
||||
|
||||
<bean id="remoteRunnnerWrapperThread" class="java.lang.Thread" init-method="start" destroy-method="interrupt">
|
||||
<constructor-arg ref="remoteRunnnerWrapper"/>
|
||||
|
||||
<!-- Bean that holds current Alfresco Spring context -->
|
||||
<bean id="org.alfresco.rad.springContextHolder" class="org.alfresco.rad.SpringContextHolder"/>
|
||||
|
||||
<!-- Web Script that can be used to invoke integration tests remotely.
|
||||
Integration testing framework donated by Zia Consulting -->
|
||||
<bean id="webscript.org.alfresco.rad.test.runtest.get"
|
||||
class="org.alfresco.rad.test.RunTestWebScript"
|
||||
parent="webscript">
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
|
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2017 Alfresco Software Limited.
|
||||
|
||||
This file is part of the Alfresco SDK project.
|
||||
|
||||
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.
|
||||
-->
|
||||
<webscript>
|
||||
<shortname>Perform Test</shortname>
|
||||
<description>Run integration test in Alfresco context</description>
|
||||
<url>/testing/test?clazz={clazz}</url>
|
||||
<format default="html">any</format>
|
||||
<lifecycle>internal</lifecycle>
|
||||
<authentication>user</authentication>
|
||||
<family>Alfresco SDK</family>
|
||||
<cache>
|
||||
<never>false</never>
|
||||
<public>false</public>
|
||||
<mustrevalidate/>
|
||||
</cache>
|
||||
<negotiate accept="text/html">html</negotiate>
|
||||
<negotiate accept="text/xml">html</negotiate>
|
||||
</webscript>
|
@@ -0,0 +1,34 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>${test?html}</title>
|
||||
<script language="JavaScript">
|
||||
function showdiv(id) {
|
||||
//safe function to show an element with a specified id
|
||||
|
||||
if (document.getElementById) { // DOM3 = IE5, NS6
|
||||
document.getElementById(id).style.display = 'block';
|
||||
}
|
||||
else {
|
||||
if (document.layers) { // Netscape 4
|
||||
document.id.display = 'block';
|
||||
}
|
||||
else { // IE 4
|
||||
document.all.id.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Integration Test: ${test?html}</h1>
|
||||
<div><b>Result:</b> ${result}</div>
|
||||
<#if failures??>
|
||||
<#list failures as failure>
|
||||
<div id="testHeader"><b>${failure.getTestHeader()?html}</b></div>
|
||||
<div id="message"><a href="#" onclick="showdiv('trace');return false;">${failure.getMessage()?html}</a></div>
|
||||
<div id="trace" style="display:none;"><pre>${failure.getTrace()?html}</pre></div>
|
||||
<br/>
|
||||
</#list>
|
||||
</#if>
|
||||
</body>
|
||||
</html>
|
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<response>
|
||||
<test>${test?html}</test>
|
||||
<result>${result?html}</result>
|
||||
<#if failures??>
|
||||
<failures>
|
||||
<#list failures as failure>
|
||||
<trace>${failure.getTrace()?html}</trace>
|
||||
<exception>${failure.getException()?html}</exception>
|
||||
<message>${failure.getMessage()?html}</message>
|
||||
<testHeader>${failure.getTestHeader()?html}</testHeader>
|
||||
</#list>
|
||||
</failures>
|
||||
</#if>
|
||||
<failureCount>${failureCount?html}</failureCount>
|
||||
<ignoreCount>${ignoreCount?html}</ignoreCount>
|
||||
<runCount>${runCount?html}</runCount>
|
||||
<runTime>${runTime?html}</runTime>
|
||||
<#if throwables??>
|
||||
<throwables>
|
||||
<#list throwables as throwable>
|
||||
<throwable>${throwable?html}</throwable>
|
||||
</#list>
|
||||
</throwables>
|
||||
</#if>
|
||||
<wasSuccessful>${wasSuccessful?string}</wasSuccessful>
|
||||
</response>
|
Reference in New Issue
Block a user