SlideShare a Scribd company logo
1 of 44
Download to read offline
APACHE SLING & FRIENDS TECH MEETUP
BERLIN, 28-30 SEPTEMBER 2015
So how do I test my Sling Application?
Robert Munteanu, Adobe Systems Romania
adaptTo() 2015
About the speaker
● Apache Sling PMC member
● Long-time Open Source contributor
● Working with Adobe on AEM
adaptTo() 2015
Agenda
● How do I test my application?
● What about Sling?
● Demo
adaptTo() 2015 4
questionQueue.add(anyQuestion());
adaptTo() 2015 5
How do I test my application?
adaptTo() 2015
Unit testing
@Test public void isNull() {
assertThat( StringUtils.isNull(
null ), is(true));
}
adaptTo() 2015
Unit testing with mocks
@Test public void persist() {
MyDao dao = mock(MyDao.class);
MyService service = new MyService(dao);
service.persist(new
ServiceObject()); // must not fail
}
adaptTo() 2015
Unit testing with mocks
@Test(expected=ServiceException.class)
public void persist() {
MyDao dao = mock(MyDao.class);
MyService service = new MyService(dao);
when(dao.persist(anyObject)).thenThrow(new
DaoUnavailableException("mocked"));
service.persist(new ServiceObject());
}
adaptTo() 2015
Integration testing
@Test public void persist() {
MyDao dao = new MyRealDao(/* config */);
MyService service = new MyService(dao);
service.persist(newServiceObject()); //
must not fail
}
adaptTo() 2015
Integration testing - clean slate
@Before public void ensureCleanSlate()
{
MyDao dao = new MyRealDao(/* config
*/);
dao.deleteAll();
}
adaptTo() 2015
End-to-end testing
@Test public void login() {
Client client = new MyBrowserBasedClient();
AuthResult result = client.login("admin",
"admin");
assertThat(result.isLoggedIn(), is(true));
}
adaptTo() 2015
Testing pyramid
adaptTo() 2015
... or the testing icecream cone?
adaptTo() 2015 14
What about Sling?
adaptTo() 2015 15
Unit testing with Sling
adaptTo() 2015
Unit testing
@Test public void test_isRedirectValid_null_empty() {
TestCase.assertFalse(AuthUtil.isRedirectValid(null,
null));
TestCase.assertFalse(AuthUtil.isRedirectValid(null,
""));
}
Actual code from AuthUtilTest.java
adaptTo() 2015
Unit testing with ad-hoc mocking
@RunWith(JMock.class) public class AuthUtilTest {
final Mockery context = new JUnit4Mockery();
final ResourceResolver resolver = context.mock(ResourceResolver.class);
final HttpServletRequest request = context.mock(HttpServletRequest.class);
@Test public void test_isRedirectValid_invalid_characters() {
context.checking(new Expectations() { /* 8 lines of code */ })
TestCase.assertFalse(AuthUtil.isRedirectValid(request,
"/illegal/</x"));
}
}
Actual code also from AuthUtilTest.java
adaptTo() 2015
Unit testing with ad-hoc mocking
context.checking(new Expectations() {
{
allowing(request).getContextPath();
will(returnValue("/ctx"));
allowing(request).getAttribute(with(any(String.class)));
will(returnValue(null));
}
});
adaptTo() 2015
Unit testing with Sling mocks
public class ModelAdapterFactoryUtilTest {
@Test public void testRequestAttribute() {
MockSlingHttpServletRequest request = new MockSlingHttpServletRequest();
request.setAttribute("prop1", "myValue");
RequestAttributeModel model =
request.adaptTo(RequestAttributeModel.class);
assertNotNull(model);
assertEquals("myValue", model.getProp1());
}
}
Actual code from ModelAdapterFactoryUtilTest.java.
adaptTo() 2015
OSGi
adaptTo() 2015
Unit testing OSGi code with Sling mocks
public class ExampleTest {
@Rule public final OsgiContext context = new OsgiContext();
@Test public void testSomething() {
// register and activate service
MyService service1 = context.registerInjectActivateService(new MyService(),
ImmutableMap.<String, Object>of("prop1", "value1"));
// get service instance
OtherService service2 = context.getService(OtherService.class);
}
}
Picked up from the OSGi mocks documentation.
adaptTo() 2015
Sling mocks
● donated to the Sling project in Octomber
2014 by Stefan Seifert
● focus on running Apache Sling in an in-
memory environment suitable for unit tests
adaptTo() 2015
The humble object pattern with OSGi
public interface RouterAdmin {
void doStuff();
}
public class RouterAdminImpl implements RouterAdmin {
// constructor and field elided
public void doStuff() { // implementation }
}
@Component @Properties({ @Property(name="url") })
public class RouterAdminComponent implements RouterAdmin {
private RouterAdmin delegate;
protected void activate(ComponentContext ctx) throws Exception {
delegate = new RouterAdminImpl(new URL(requireString(ctx, "url")));
}
public void doStuff() {
delegate.doStuff();
}
}
adaptTo() 2015
JCR
adaptTo() 2015
Testing JCR code with Sling mocks
public class FindResourcesTest {
@Rule public SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
@Before public void setUp() {
Resource resource = context.create().resource("test",
ImmutableMap.<String, Object> builder().put("prop1", "value1")
.put("prop2", "value2").build());
// snip ...
MockJcr.setQueryResult(session, Collections.singletonList(node));
}
@Test public void testFindResources() {
Resource resource = context.resourceResolver().getResource("/test");
Assert.assertNotNull("Resource with name 'test' should be there", resource);
Iterator<Resource> result = context.resourceResolver().findResources("/test", Query.XPATH);
Assert.assertTrue("At least one result expected", result.hasNext());
Assert.assertEquals("/test", result.next().getPath());
Assert.assertFalse("At most one result expected", result.hasNext());
}
}
Code taken from FindResourceTest.java .
adaptTo() 2015
Sling
adaptTo() 2015
Sling Mocks for unit testing
public class SimpleNoSqlResourceProviderQueryTest {
@Rule public SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
@Before public void setUp() throws Exception {
context.registerInjectActivateService(new SimpleNoSqlResourceProviderFactory(), ImmutableMap.<String, Object>builder()
.put(ResourceProvider.ROOTS, "/nosql-simple")
.build());
// prepare some test data using Sling CRUD API ( not shown here )
}
@Test
public void testFindResources_ValidQuery() {
Iterator<Resource> result = context.resourceResolver().findResources("all", "simple");
assertEquals("/nosql-simple", result.next().getPath());
assertEquals("/nosql-simple/test", result.next().getPath());
assertEquals("/nosql-simple/test/node1", result.next().getPath());
assertEquals("/nosql-simple/test/node2", result.next().getPath());
assertFalse(result.hasNext());
}
}
Code from SimpleNoSqlResourceProviderQueryTest
adaptTo() 2015
Sling Mocks for unit testing
adaptTo() 2015
Sling Mocks for unit testing
adaptTo() 2015
Hamcrest matchers
@Test public void loadResources() {
Map<String, Object> expectedProperties = /* define properties */;
Resource resource = /* load resource */ null;
assertThat(resource, resourceOfType("my/app"));
assertThat(resource, hasChildren("header", "body"));
assertThat(resource, resourceWithProps(expectedProperties));
}
Taken from the Hamcrest integration documentation.
adaptTo() 2015 31
Integration testing with Sling
adaptTo() 2015
Pax-Exam
public static Option[] paxConfig() {
final File thisProjectsBundle = new File(System.getProperty( "bundle.file.name",
"BUNDLE_FILE_NOT_SET" ));
final String launchpadVersion = System.getProperty("sling.launchpad.version",
"LAUNCHPAD_VERSION_NOT_SET");
log.info("Sling launchpad version: {}", launchpadVersion);
return new DefaultCompositeOption(
SlingPaxOptions.defaultLaunchpadOptions(launchpadVersion),
CoreOptions.provision(CoreOptions.bundle(thisProjectsBundle.toURI().toString()))
).getOptions();
}
Taken from U.java
adaptTo() 2015
Pax-Exam
@RunWith(PaxExam.class) public class FileNameExtractorImplIT {
@Inject private FileNameExtractor fileNameExtractor;
@Test public void testFileNameExtractor(){
String rawPath = "http://midches.com/images/uploads/default/demo.jpg#anchor?query=test";
String expectedFileName = "demo.jpg";
assertEquals(expectedFileName, fileNameExtractor.extract(rawPath));
}
@Configuration public Option[] config() {
return U.paxConfig();
}
}
Taken from FileNameExtractorImplIT.java.
adaptTo() 2015
Sling mocks with a JCR backend
● Unit testing with JCR Mocks
– JCR_MOCK
– SLING_MOCK
● Integration testing with JCR Mocks
– JCR_JACKRABBIT
– JCR_OAK
adaptTo() 2015
Server-side JUnit tests
public class ServerSideInstallerTest {
@Rule public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "Launchpad");
@Before
public void setup() throws LoginException {
ip = teleporter.getService(InfoProvider.class);
is = ip.getInstallationState();
}
@Test
public void noUntransformedResources() {
final List<?> utr = is.getUntransformedResources();
if(utr.size() > 0) {
fail("Untransformed resources found: " + utr);
}
}
}
adaptTo() 2015
Scriptable server-side tests
// test imports that fail on Java 8, SLING-3405
%><%@page import="java.util.Arrays"%><%
%><%@page import="java.lang.CharSequence"%><%
%>TEST_PASSED
Actual code from installer-duplicate.jsp.
adaptTo() 2015 37
End-to-end testing with Sling
adaptTo() 2015
HTTP utilities from the Sling testing tools
public class HttpPingTest extends HttpTestBase {
public void testWebServerRoot() throws Exception {
// by default, the Launchpad default servlet redirects / to index.html
final String url = HTTP_BASE_URL + "/";
final GetMethod get = new GetMethod(url);
get.setFollowRedirects(false);
final int status = httpClient.executeMethod(get);
assertEquals("Status must be 302 for " + url, 302, status);
final Header h = get.getResponseHeader("Location");
assertNotNull("Location header must be provided",h);
assertTrue("Location header must end with index.html",
h.getValue().endsWith("index.html"));
}
}
Code taken from HttpPingTest.java
adaptTo() 2015 39
Code time
adaptTo() 2015
Slingshot
adaptTo() 2015
Final thoughts
● Sling provides a lot of specialised testing
tools
● Lots of effort recently invested in the unit
testing layer
● Experiment and provide feedback
● Contributions are definitely welcomed
adaptTo() 2015
Resources
● https://sling.apache.org/documentation/d
evelopment/sling-mock.html
● http://wcm.io/testing/aem-mock/
● http://svn.apache.org/repos/asf/sling/trun
k/samples/slingshot/
● http://xunitpatterns.com/Humble%20Obje
ct.html
adaptTo() 2015
Colophon
● Presentation crafted with Eclipse, GNU Make and odpdown
● Photo credits
– Slingshots by Anne and Tim on Flickr
– Wall by Bart Lumber on Flickr
– HTML code by Marjan Krebelj on Flickr
– Foggy Oak Tree by Brett Whaley on Flickr
● Testing pyramid and ice-cream cone concepts courtesy of
watirmelon.com
adaptTo() 2015
Q&A

More Related Content

What's hot

Spring boot 3g
Spring boot 3gSpring boot 3g
Spring boot 3g
vasya10
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat Tool
Kanika2885
 
Ratpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web AppsRatpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web Apps
James Williams
 
EclipseMAT
EclipseMATEclipseMAT
EclipseMAT
Ali Bahu
 
Apache Ant
Apache AntApache Ant
Apache Ant
Ali Bahu
 

What's hot (20)

Spring boot 3g
Spring boot 3gSpring boot 3g
Spring boot 3g
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Ant - Another Neat Tool
Ant - Another Neat ToolAnt - Another Neat Tool
Ant - Another Neat Tool
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
Apache ant
Apache antApache ant
Apache ant
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling Rewriter
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
 
Desktop|Embedded Application API JSR
Desktop|Embedded Application API JSRDesktop|Embedded Application API JSR
Desktop|Embedded Application API JSR
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
Ratpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web AppsRatpack - Classy and Compact Groovy Web Apps
Ratpack - Classy and Compact Groovy Web Apps
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
EclipseMAT
EclipseMATEclipseMAT
EclipseMAT
 
Apache Ant
Apache AntApache Ant
Apache Ant
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
 
JavaLand - Integration Testing How-to
JavaLand - Integration Testing How-toJavaLand - Integration Testing How-to
JavaLand - Integration Testing How-to
 
AEM and Sling
AEM and SlingAEM and Sling
AEM and Sling
 
Spring boot
Spring bootSpring boot
Spring boot
 

Viewers also liked

Sling models by Justin Edelson
Sling models by Justin Edelson Sling models by Justin Edelson
Sling models by Justin Edelson
AEM HUB
 
Build single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEMBuild single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEM
connectwebex
 

Viewers also liked (7)

JCR, Sling or AEM? Which API should I use and when?
JCR, Sling or AEM? Which API should I use and when?JCR, Sling or AEM? Which API should I use and when?
JCR, Sling or AEM? Which API should I use and when?
 
Introduction to Sightly and Sling Models
Introduction to Sightly and Sling ModelsIntroduction to Sightly and Sling Models
Introduction to Sightly and Sling Models
 
Build single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEMBuild single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEM
 
Sling models by Justin Edelson
Sling models by Justin Edelson Sling models by Justin Edelson
Sling models by Justin Edelson
 
Effective Web Application Development with Apache Sling
Effective Web Application Development with Apache SlingEffective Web Application Development with Apache Sling
Effective Web Application Development with Apache Sling
 
AEM Sightly Deep Dive
AEM Sightly Deep DiveAEM Sightly Deep Dive
AEM Sightly Deep Dive
 
Build single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEMBuild single page applications using AngularJS on AEM
Build single page applications using AngularJS on AEM
 

Similar to So how do I test my Sling application?

UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
Tobias Schneck
 

Similar to So how do I test my Sling application? (20)

Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...Building domain-specific testing tools : lessons learned from the Apache Slin...
Building domain-specific testing tools : lessons learned from the Apache Slin...
 
Gwt.create
Gwt.createGwt.create
Gwt.create
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Appium Automation with Kotlin
Appium Automation with KotlinAppium Automation with Kotlin
Appium Automation with Kotlin
 
Junit and testNG
Junit and testNGJunit and testNG
Junit and testNG
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin Edelson
 
Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
 
JCConf 2016 - Dataflow Workshop Labs
JCConf 2016 - Dataflow Workshop LabsJCConf 2016 - Dataflow Workshop Labs
JCConf 2016 - Dataflow Workshop Labs
 
Amazon elastic map reduce
Amazon elastic map reduceAmazon elastic map reduce
Amazon elastic map reduce
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
UI Testing - Selenium? Rich-Clients? Containers? (SwanseaCon 2018)
 
Androidaop 170105090257
Androidaop 170105090257Androidaop 170105090257
Androidaop 170105090257
 
Proxy Deep Dive JUG Saxony Day 2015-10-02
Proxy Deep Dive JUG Saxony Day 2015-10-02Proxy Deep Dive JUG Saxony Day 2015-10-02
Proxy Deep Dive JUG Saxony Day 2015-10-02
 
Testing your application on Google App Engine
Testing your application on Google App EngineTesting your application on Google App Engine
Testing your application on Google App Engine
 
Testing Your Application On Google App Engine
Testing Your Application On Google App EngineTesting Your Application On Google App Engine
Testing Your Application On Google App Engine
 
Dropwizard and Friends
Dropwizard and FriendsDropwizard and Friends
Dropwizard and Friends
 
Android testing
Android testingAndroid testing
Android testing
 

More from Robert Munteanu

More from Robert Munteanu (20)

Secure by Default Web Applications
Secure by Default Web ApplicationsSecure by Default Web Applications
Secure by Default Web Applications
 
Sling Applications - A DevOps perspective
Sling Applications - A DevOps perspectiveSling Applications - A DevOps perspective
Sling Applications - A DevOps perspective
 
Will it blend? Java agents and OSGi
Will it blend? Java agents and OSGiWill it blend? Java agents and OSGi
Will it blend? Java agents and OSGi
 
Escape the defaults - Configure Sling like AEM as a Cloud Service
Escape the defaults - Configure Sling like AEM as a Cloud ServiceEscape the defaults - Configure Sling like AEM as a Cloud Service
Escape the defaults - Configure Sling like AEM as a Cloud Service
 
Crash course in Kubernetes monitoring
Crash course in Kubernetes monitoringCrash course in Kubernetes monitoring
Crash course in Kubernetes monitoring
 
Java agents for fun and (not so much) profit
Java agents for fun and (not so much) profitJava agents for fun and (not so much) profit
Java agents for fun and (not so much) profit
 
Will it blend? Java agents and OSGi
Will it blend? Java agents and OSGiWill it blend? Java agents and OSGi
Will it blend? Java agents and OSGi
 
Cloud-native legacy applications
Cloud-native legacy applicationsCloud-native legacy applications
Cloud-native legacy applications
 
Cloud-Native Sling
Cloud-Native SlingCloud-Native Sling
Cloud-Native Sling
 
From Monolith to Modules - breaking apart a one size fits all product into mo...
From Monolith to Modules - breaking apart a one size fits all product into mo...From Monolith to Modules - breaking apart a one size fits all product into mo...
From Monolith to Modules - breaking apart a one size fits all product into mo...
 
What's new in the Sling developer tooling?
What's new in the Sling developer tooling?What's new in the Sling developer tooling?
What's new in the Sling developer tooling?
 
Scaling up development of a modular code base
Scaling up development of a modular code baseScaling up development of a modular code base
Scaling up development of a modular code base
 
Scaling up development of a modular code base
Scaling up development of a modular code baseScaling up development of a modular code base
Scaling up development of a modular code base
 
Scaling up development of a modular code base
Scaling up development of a modular code baseScaling up development of a modular code base
Scaling up development of a modular code base
 
Zero downtime deployments for Sling application using Docker
Zero downtime deployments for Sling application using DockerZero downtime deployments for Sling application using Docker
Zero downtime deployments for Sling application using Docker
 
Scaling up development of a modular code base
Scaling up development of a modular code baseScaling up development of a modular code base
Scaling up development of a modular code base
 
Do you really want to go fully micro?
Do you really want to go fully micro?Do you really want to go fully micro?
Do you really want to go fully micro?
 
Effective web application development with Apache Sling
Effective web application development with Apache SlingEffective web application development with Apache Sling
Effective web application development with Apache Sling
 
Of microservices and microservices
Of microservices and microservicesOf microservices and microservices
Of microservices and microservices
 
Slide IDE Tooling (adaptTo 2016)
Slide IDE Tooling (adaptTo 2016)Slide IDE Tooling (adaptTo 2016)
Slide IDE Tooling (adaptTo 2016)
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 

So how do I test my Sling application?

  • 1. APACHE SLING & FRIENDS TECH MEETUP BERLIN, 28-30 SEPTEMBER 2015 So how do I test my Sling Application? Robert Munteanu, Adobe Systems Romania
  • 2. adaptTo() 2015 About the speaker ● Apache Sling PMC member ● Long-time Open Source contributor ● Working with Adobe on AEM
  • 3. adaptTo() 2015 Agenda ● How do I test my application? ● What about Sling? ● Demo
  • 5. adaptTo() 2015 5 How do I test my application?
  • 6. adaptTo() 2015 Unit testing @Test public void isNull() { assertThat( StringUtils.isNull( null ), is(true)); }
  • 7. adaptTo() 2015 Unit testing with mocks @Test public void persist() { MyDao dao = mock(MyDao.class); MyService service = new MyService(dao); service.persist(new ServiceObject()); // must not fail }
  • 8. adaptTo() 2015 Unit testing with mocks @Test(expected=ServiceException.class) public void persist() { MyDao dao = mock(MyDao.class); MyService service = new MyService(dao); when(dao.persist(anyObject)).thenThrow(new DaoUnavailableException("mocked")); service.persist(new ServiceObject()); }
  • 9. adaptTo() 2015 Integration testing @Test public void persist() { MyDao dao = new MyRealDao(/* config */); MyService service = new MyService(dao); service.persist(newServiceObject()); // must not fail }
  • 10. adaptTo() 2015 Integration testing - clean slate @Before public void ensureCleanSlate() { MyDao dao = new MyRealDao(/* config */); dao.deleteAll(); }
  • 11. adaptTo() 2015 End-to-end testing @Test public void login() { Client client = new MyBrowserBasedClient(); AuthResult result = client.login("admin", "admin"); assertThat(result.isLoggedIn(), is(true)); }
  • 13. adaptTo() 2015 ... or the testing icecream cone?
  • 14. adaptTo() 2015 14 What about Sling?
  • 15. adaptTo() 2015 15 Unit testing with Sling
  • 16. adaptTo() 2015 Unit testing @Test public void test_isRedirectValid_null_empty() { TestCase.assertFalse(AuthUtil.isRedirectValid(null, null)); TestCase.assertFalse(AuthUtil.isRedirectValid(null, "")); } Actual code from AuthUtilTest.java
  • 17. adaptTo() 2015 Unit testing with ad-hoc mocking @RunWith(JMock.class) public class AuthUtilTest { final Mockery context = new JUnit4Mockery(); final ResourceResolver resolver = context.mock(ResourceResolver.class); final HttpServletRequest request = context.mock(HttpServletRequest.class); @Test public void test_isRedirectValid_invalid_characters() { context.checking(new Expectations() { /* 8 lines of code */ }) TestCase.assertFalse(AuthUtil.isRedirectValid(request, "/illegal/</x")); } } Actual code also from AuthUtilTest.java
  • 18. adaptTo() 2015 Unit testing with ad-hoc mocking context.checking(new Expectations() { { allowing(request).getContextPath(); will(returnValue("/ctx")); allowing(request).getAttribute(with(any(String.class))); will(returnValue(null)); } });
  • 19. adaptTo() 2015 Unit testing with Sling mocks public class ModelAdapterFactoryUtilTest { @Test public void testRequestAttribute() { MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(); request.setAttribute("prop1", "myValue"); RequestAttributeModel model = request.adaptTo(RequestAttributeModel.class); assertNotNull(model); assertEquals("myValue", model.getProp1()); } } Actual code from ModelAdapterFactoryUtilTest.java.
  • 21. adaptTo() 2015 Unit testing OSGi code with Sling mocks public class ExampleTest { @Rule public final OsgiContext context = new OsgiContext(); @Test public void testSomething() { // register and activate service MyService service1 = context.registerInjectActivateService(new MyService(), ImmutableMap.<String, Object>of("prop1", "value1")); // get service instance OtherService service2 = context.getService(OtherService.class); } } Picked up from the OSGi mocks documentation.
  • 22. adaptTo() 2015 Sling mocks ● donated to the Sling project in Octomber 2014 by Stefan Seifert ● focus on running Apache Sling in an in- memory environment suitable for unit tests
  • 23. adaptTo() 2015 The humble object pattern with OSGi public interface RouterAdmin { void doStuff(); } public class RouterAdminImpl implements RouterAdmin { // constructor and field elided public void doStuff() { // implementation } } @Component @Properties({ @Property(name="url") }) public class RouterAdminComponent implements RouterAdmin { private RouterAdmin delegate; protected void activate(ComponentContext ctx) throws Exception { delegate = new RouterAdminImpl(new URL(requireString(ctx, "url"))); } public void doStuff() { delegate.doStuff(); } }
  • 25. adaptTo() 2015 Testing JCR code with Sling mocks public class FindResourcesTest { @Rule public SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK); @Before public void setUp() { Resource resource = context.create().resource("test", ImmutableMap.<String, Object> builder().put("prop1", "value1") .put("prop2", "value2").build()); // snip ... MockJcr.setQueryResult(session, Collections.singletonList(node)); } @Test public void testFindResources() { Resource resource = context.resourceResolver().getResource("/test"); Assert.assertNotNull("Resource with name 'test' should be there", resource); Iterator<Resource> result = context.resourceResolver().findResources("/test", Query.XPATH); Assert.assertTrue("At least one result expected", result.hasNext()); Assert.assertEquals("/test", result.next().getPath()); Assert.assertFalse("At most one result expected", result.hasNext()); } } Code taken from FindResourceTest.java .
  • 27. adaptTo() 2015 Sling Mocks for unit testing public class SimpleNoSqlResourceProviderQueryTest { @Rule public SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK); @Before public void setUp() throws Exception { context.registerInjectActivateService(new SimpleNoSqlResourceProviderFactory(), ImmutableMap.<String, Object>builder() .put(ResourceProvider.ROOTS, "/nosql-simple") .build()); // prepare some test data using Sling CRUD API ( not shown here ) } @Test public void testFindResources_ValidQuery() { Iterator<Resource> result = context.resourceResolver().findResources("all", "simple"); assertEquals("/nosql-simple", result.next().getPath()); assertEquals("/nosql-simple/test", result.next().getPath()); assertEquals("/nosql-simple/test/node1", result.next().getPath()); assertEquals("/nosql-simple/test/node2", result.next().getPath()); assertFalse(result.hasNext()); } } Code from SimpleNoSqlResourceProviderQueryTest
  • 28. adaptTo() 2015 Sling Mocks for unit testing
  • 29. adaptTo() 2015 Sling Mocks for unit testing
  • 30. adaptTo() 2015 Hamcrest matchers @Test public void loadResources() { Map<String, Object> expectedProperties = /* define properties */; Resource resource = /* load resource */ null; assertThat(resource, resourceOfType("my/app")); assertThat(resource, hasChildren("header", "body")); assertThat(resource, resourceWithProps(expectedProperties)); } Taken from the Hamcrest integration documentation.
  • 31. adaptTo() 2015 31 Integration testing with Sling
  • 32. adaptTo() 2015 Pax-Exam public static Option[] paxConfig() { final File thisProjectsBundle = new File(System.getProperty( "bundle.file.name", "BUNDLE_FILE_NOT_SET" )); final String launchpadVersion = System.getProperty("sling.launchpad.version", "LAUNCHPAD_VERSION_NOT_SET"); log.info("Sling launchpad version: {}", launchpadVersion); return new DefaultCompositeOption( SlingPaxOptions.defaultLaunchpadOptions(launchpadVersion), CoreOptions.provision(CoreOptions.bundle(thisProjectsBundle.toURI().toString())) ).getOptions(); } Taken from U.java
  • 33. adaptTo() 2015 Pax-Exam @RunWith(PaxExam.class) public class FileNameExtractorImplIT { @Inject private FileNameExtractor fileNameExtractor; @Test public void testFileNameExtractor(){ String rawPath = "http://midches.com/images/uploads/default/demo.jpg#anchor?query=test"; String expectedFileName = "demo.jpg"; assertEquals(expectedFileName, fileNameExtractor.extract(rawPath)); } @Configuration public Option[] config() { return U.paxConfig(); } } Taken from FileNameExtractorImplIT.java.
  • 34. adaptTo() 2015 Sling mocks with a JCR backend ● Unit testing with JCR Mocks – JCR_MOCK – SLING_MOCK ● Integration testing with JCR Mocks – JCR_JACKRABBIT – JCR_OAK
  • 35. adaptTo() 2015 Server-side JUnit tests public class ServerSideInstallerTest { @Rule public final TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "Launchpad"); @Before public void setup() throws LoginException { ip = teleporter.getService(InfoProvider.class); is = ip.getInstallationState(); } @Test public void noUntransformedResources() { final List<?> utr = is.getUntransformedResources(); if(utr.size() > 0) { fail("Untransformed resources found: " + utr); } } }
  • 36. adaptTo() 2015 Scriptable server-side tests // test imports that fail on Java 8, SLING-3405 %><%@page import="java.util.Arrays"%><% %><%@page import="java.lang.CharSequence"%><% %>TEST_PASSED Actual code from installer-duplicate.jsp.
  • 37. adaptTo() 2015 37 End-to-end testing with Sling
  • 38. adaptTo() 2015 HTTP utilities from the Sling testing tools public class HttpPingTest extends HttpTestBase { public void testWebServerRoot() throws Exception { // by default, the Launchpad default servlet redirects / to index.html final String url = HTTP_BASE_URL + "/"; final GetMethod get = new GetMethod(url); get.setFollowRedirects(false); final int status = httpClient.executeMethod(get); assertEquals("Status must be 302 for " + url, 302, status); final Header h = get.getResponseHeader("Location"); assertNotNull("Location header must be provided",h); assertTrue("Location header must end with index.html", h.getValue().endsWith("index.html")); } } Code taken from HttpPingTest.java
  • 41. adaptTo() 2015 Final thoughts ● Sling provides a lot of specialised testing tools ● Lots of effort recently invested in the unit testing layer ● Experiment and provide feedback ● Contributions are definitely welcomed
  • 42. adaptTo() 2015 Resources ● https://sling.apache.org/documentation/d evelopment/sling-mock.html ● http://wcm.io/testing/aem-mock/ ● http://svn.apache.org/repos/asf/sling/trun k/samples/slingshot/ ● http://xunitpatterns.com/Humble%20Obje ct.html
  • 43. adaptTo() 2015 Colophon ● Presentation crafted with Eclipse, GNU Make and odpdown ● Photo credits – Slingshots by Anne and Tim on Flickr – Wall by Bart Lumber on Flickr – HTML code by Marjan Krebelj on Flickr – Foggy Oak Tree by Brett Whaley on Flickr ● Testing pyramid and ice-cream cone concepts courtesy of watirmelon.com