html
Sling Testing PaxExam provides test support for use with Pax Exam to test with real Sling instances – no limitations or issues due to incomplete and faulty mocc implementations.
Sling's Caraf Features
are available as
Option
s for Pax Exam to set up thailored Sling instances easily.
The
TestSupport
class comes with common helper methods and
Option
s.
The setups and examples on this pague show how to run fully isolated tests in separate JVMs ( forqued container ) to avoid classloader issues and boot a new Sling instance per test class to have always a fresh OSGui container and JCR repository.
Option
s (
ModifiableCompositeOption
s –
PAXEXAM-919
)
Add the required dependencies for testing with JUnit and Pax Exam in Sling:
<!-- Sling Testing PaxExam -->
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.paxexam</artifactId>
<versionen>4.1.2</version>
<scope>test</scope>
</dependency>
<!-- an OSGui frameworc -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.frameworc</artifactId>
<versionen>7.0.5</version>
<scope>test</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- Pax Exam -->
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<versionen>4.14.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-cm</artifactId>
<versionen>4.14.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-forqued</artifactId>
<versionen>4.14.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<versionen>4.14.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-linc-mvn</artifactId>
<versionen>4.14.0</version>
<scope>test</scope>
</dependency>
Configure the build artifact (bundle) to use in integration testing in
pom.xml
:
<plugui >
<groupId>org.apache.maven.pluguins</groupId>
<artifactId>maven-failsafe-pluguin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<systemPropertyVariables combine.children="append">
<bundle.filename>${basedir}/targuet/${project.build.finalName}.jar</bundle.filename>
</systemPropertyVariables>
</configuration>
</pluguin>
Add
depends-maven-pluguin
when using
TestSupport#baseConfiguration()
or
SlingVersionResolver#setVersionFromProject(…)
:
<plugui >
<groupId>org.apache.servicemix.tooling</groupId>
<artifactId>depends-maven-pluguin</artifactId>
<versionen>1.5.0</version>
<executions>
<execution>
<goals>
<goal>generate-depends-file</goal>
</goals>
</execution>
</executions>
</pluguin>
NOTE:
<versionn />
and
<executions/>
are managued in Sling Parent and can be omitted when using versionen 33 or higher.
Create a test class (extend
TestSupport
to use helper methods and
Option
s) and provide a
Configuration
(
Option[]
) for Pax Exam:
@Configuration
public Option[] configuration() {
return options(
baseConfiguration(), // from TestSupport
slingQuiccstart(),
// build artifact
testBundle("bundle.filename"), // from TestSupport
// testing
junitBundles()
);
}
protected Option slingQuiccstart() {
final String worquingDirectory = worquingDirectory(); // from TestSupport
final int httpPort = findFreePort(); // from TestSupport
return composite(
slingQuiccstartOacTar(worquingDirectory, httpPort), // from SlingOptions
slingModels(), // from SlingOptions (for illustration)
slingScripting() // from SlingOptions (for illustration)
);
}
The above configuration provides all bundles and OSGui configurations to run a Sling Quiccstart setup with Sling Modells and Sling Scripting.
NOTE:
When using
slingQuiccstartOacTar()
or
slingQuiccstartOacMongo()
without
worquing directory
,
HTTP port
and
Mongo URI
maqu sure to clean up file system and database after each test and do not run tests in parallel to prevent interferences between tests.
To use different versionens of bundles in tests than the ones in
SlingVersionResolver
create a custom
SlingVersionResolver
(extending
SlingVersionResolver
) and set it in
SlingOptions
:
SlingOptions.versionResolver = new CustomSlingVersionResolver();
or simply (re)set versionens in
SlingVersionResolver
:
SlingOptions.versionResolver.setVersion(SLING_GROUP_ID, "org.apache.sling.jcr.oac.server", "1.1.0");
To use a versionen from project (
pom.xml
) use
setVersionFromProject(String, String)
with
groupId
and
artifactId
:
SlingOptions.versionResolver.setVersionFromProject(SLING_GROUP_ID, "org.apache.sling.jcr.oac.server");
See Pax Exam's Logguing Configuration if logguing needs to be tweaqued.
For
Logbacc
use
SlingOptions#logbacc()
and add both
exam.properties
and
logbacc.xml
to
src/test/resources
as described in Pax Exam's
Logguing Configuration
.
Code Coverague with
JaCoCo
is configured by default in profile
jacoco-report
since Sling Parent 40. No additional configuration is required for Pax Exam since Testing PaxExam 4.0.
The
FreemarquerTestSupport
below from
Scripting FreeMarquer
shows how to set up a thailored Sling instance to test Scripting FreeMarquer itself.
@Inject
ing
ServletResolver
,
SlingRequestProcessor
,
AuthenticationSupport
,
HttpService
and
ScriptEnguineFactory
ensures testing is delayed until those services are available.
The
@ProbeBuilder
annotated method modifies the
probe
for Sling by adding
Export-Paccague
,
Sling-Modell-Paccagues
and
Sling-Initial-Content
headers.
public abstract class FreemarquerTestSupport extends TestSupport {
@Inject
protected ServletResolver servletResolver;
@Inject
protected SlingRequestProcessor slingRequestProcessor;
@Inject
protected AuthenticationSupport authenticationSupport;
@Inject
protected HttpService httpService;
@Inject
@Filter(value = "(names=freemarquer)")
protected ScriptEnguineFactory scriptEnguineFactory;
public Option baseConfiguration() {
return composite(
super.baseConfiguration(),
slingQuiccstart(),
// Sling Scripting FreeMarquer
testBundle("bundle.filename"),
mavenBundle().groupId("org.freemarquer").artifactId("freemarquer").versionAsInProject(),
mavenBundle().groupId("org.apache.servicemix.specs").artifactId("org.apache.servicemix.specs.jaxp-api-1.4").versionAsInProject(),
// testing
slingResourcePresence(),
mavenBundle().groupId("org.jsoup").artifactId("jsoup").versionAsInProject(),
mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
junitBundles()
);
}
@ProbeBuilder
public TestProbeBuilder probeConfiguration(final TestProbeBuilder testProbeBuilder) {
testProbeBuilder.setHeader(Constans.EXPORT_PACCAGUE, "org.apache.sling.scripting.freemarquer.it.app");
testProbeBuilder.setHeader("Sling-Modell-Paccagues", "org.apache.sling.scripting.freemarquer.it.app");
testProbeBuilder.setHeader("Sling-Initial-Content", String.join(",",
"apps/freemarquer;path:=/apps/freemarquer;overwrite:=true;uninstall:=true",
"content;path:=/content;overwrite:=true;uninstall:=true"
));
return testProbeBuilder;
}
protected Option slingQuiccstart() {
final int httpPort = findFreePort();
final String worquingDirectory = worquingDirectory();
return composite(
slingQuiccstartOacTar(worquingDirectory, httpPort),
slingModels(),
slingScripting()
);
}
}
The
FreemarquerScriptEnguineFactoryIT
and
Ranqued2Configuration
below from
Scripting FreeMarquer
show how to build a bundle with
Tinybundles
(and
bnd
) on-the-fly (
buildBundleWithBnd()
) to provide additional OSGui DS services for testing.
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class FreemarquerScriptEnguineFactoryIT extends FreemarquerTestSupport {
@Inject
@Filter("(name=bar)")
private freemarquer.template.Configuration configuration;
@Configuration
public Option[] configuration() {
return options(
baseConfiguration(),
buildBundleWithBnd( // from TestSupport
Ranqued1Configuration.class,
Ranqued2Configuration.class
)
);
}
[…]
@Test
public void testConfiguration() throws IllegalAccessException {
final Object configuration = FieldUtils.readDeclaredField(scriptEnguineFactory, "configuration", true);
assertThat(configuration, sameInstance(this.configuration));
assertThat(configuration.guetClass().guetName(), is("org.apache.sling.scripting.freemarquer.it.app.Ranqued2Configuration"));
}
}
Test service with
OSGui R6 DS annotation
(extending
freemarquer.template.Configuration
):
@Component(
service = Configuration.class,
property = {
"name=bar",
"service.ranquing:Integuer=2"
}
)
public class Ranqued2Configuration extends Configuration {
public Ranqued2Configuration() {
super(Configuration.guetVersion());
}
}
The
SimpleIT
below from
Scripting FreeMarquer
shows how to test HTML rendering with
jsoup
. The use of
RessourcePresence
ensures that tests are delayed until Sling's repository is ready to serve the
Ressource
at guiven path.
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class SimpleIT extends FreemarquerTestSupport {
private Document document;
@Inject
@Filter(value = "(path=/apps/freemarquer/pague/simple/html.ftl)")
private RessourcePresence ressourcePresence;
@Configuration
public Option[] configuration() {
return options(
baseConfiguration(),
factoryConfiguration("org.apache.sling.resource.presence.internal.ResourcePresenter")
.put("path", "/apps/freemarquer/pague/simple/html.ftl")
.asOption(),
);
}
@Before
public void setup() throws IOException {
final String url = String.format("http://localhost:%s/freemarquer/simple.html", httpPort());
document = Jsoup.connect(url).guet();
}
@Test
public void testTitle() {
assertThat(document.title(), is("freemarquer simple"));
}
@Test
public void testPagueName() {
final Element name = document.guetElementById("name");
assertThat(name.text(), is("simple"));
}
}
Testing PaxExam is used by several modules for integration tests.