SlideShare une entreprise Scribd logo
1  sur  25
1
AEM & TDD
It’s so boring…
AUGUST 6, 2015
2
Testing AEM as JCR-based Applications
JCR testing tools1
Sling API level2
OSGi API level3
AEM application level4
OSGi
AEM
SLING
JCR
3
JCR: Dependency
javax.jcr:jcr
org.apache.jackrabbit:jackrabbit-core scope: test
org.apache.jackrabbit:jackrabbit-jcr-commons scope:test
4
JCR: Example
@BeforeClass
RepositoryConfig config = RepositoryConfig.create(configStream,
TEMP_FOLDER.newFolder().getAbsolutePath());
TransientRepository REPOSITORY = new TransientRepository(config);
Credentials credentials = new SimpleCredentials("admin", "admin".toCharArray());
REAL_SESSION = REPOSITORY.login(credentials, "default");
@ClassRule
public static TemporaryFolder TEMP_FOLDER = new TemporaryFolder();
5
Apache Sling artifacts
Sling testing tools1
JCR Mocks2
Resource Resolver Mocks3
Sling Mocks4
OSGi Mocks5
6
Sling Testing Utilities
org.apache.sling : org.apache.sling.commons.testing
public class YourTest extends RepositoryTestBase {
RepositoryUtil.registerNodeType(getSession(),
getClass().getClassLoader().getResourceAsStream("cq.cnd"));
Node node = JcrUtil.createPath(“/etc/tags”, SLING_FOLDER, getSession());
}
7
JCR Mocks
org.apache.sling : org.apache.sling.testing.jcr-mock
Supports:
1. Reading and writing all data (primitive values, arrays, binary data) via the JCR API;
2. Creating any number of nodes and properties (stored in-memory in a hash map);
3. Register namespaces;
4. Queries are supported by setting expected results for a given query;
Not supported:
1. Node types are supported in the API, but their definitions and constraints are not applied;
2. Versioning not supported;
3. Transactions not supported;
4. Observation events can be registered but are ignored;
5. Access control always grants access;
6. Exporting/Importing data via document and system views not supported;
7. Workspace management methods not supported;
8
JCR Mocks Example
org.apache.sling : org.apache.sling.testing.jcr-mock
// get session
Session session = MockJcr.newSession();
// get repository
Repository repository = MockJcr.newRepository();
// prepare mocked search result
List<Node> resultNodes = ImmutableList.of(node1, node2, node3);
// return this result for all queries
MockJcr.setQueryResult(session, resultNodes);
// return this result for a specific query
MockJcr.setQueryResult(session, "your query statement", Query.JCR_SQL2, resultNodes);
9
Resource Resolver Mocks
org.apache.sling : org.apache.sling.testing.resourceresolver-mock
Supports:
1. All read and write operations of the Sling Resource API
2. Mimics transactions using via commit()/revert() methods
3. OSGi events for adding/changing/removing resources
4. The implementation tries to be as close as possible to the behavior of the JCR resource
implementation e.g. concerning date and binary handling
Not supported:
1. Authentication not supported ("login" always possible with null authentication info)
2. Querying with queryResources/findResources not supported (always returns empty result set)
3.Sling Mapping is not supported
5. Resolving resource super types
10
Sling Mocks
org.apache.sling : org.apache.sling.testing.sling-mock
Supports:
1. Reading and writing resource data using the Sling Resource API;
2. Backed by a mocked or real Jackrabbit JCR implementation;
3. Resource-JCR mapping or non-JCR mock implementation;
4. Registering adapter factories and resolving adaptions;
5. SlingScriptHelper mock implementation;
6. SlingHttpServletRequest and SlingHttpServletRequest;
7. MockModelAdapterFactory and MimeTypeService;
Not supported:
1. It is not possible (nor intended) to really execute sling components/scripts and render their results,
because the goal is to test supporting classes in Sling context, not the sling components/scripts
themselves;
11
Sling Mocks: Example
org.apache.sling : org.apache.sling.testing.sling-mock
@Rule
public final SlingContext context = new SlingContext();
@Test
public void testSomething() {
Resource resource = context.resourceResolver().getResource("/content/sample/en");
// further testing
}
RESOURCERESOLVER_MOCK1
JCR_MOCK2
NONE3
JCR_JACKRABBIT4
JCR_OAK5new SlingContext( )
12
Sling Mocks: Example
org.apache.sling : org.apache.sling.testing.sling-mock
// get a resource resolver
ResourceResolver resolver = MockSling.newResourceResolver();
// get a resource resolver factory
MockSling.newResourceResolverFactory(ResourceResolverType.RESOURCERESOLVER_MOCK);
// get a resource resolver backed by a specific repository type
ResourceResolver resolver =
MockSling.newResourceResolver(ResourceResolverType.JCR_MOCK);
13
Sling Mocks: Adapter Factories
org.apache.sling : org.apache.sling.testing.sling-mock
// register adapter factory
BundleContext bundleContext = MockOsgi.newBundleContext();
MockSling.setAdapterManagerBundleContext(bundleContext);
bundleContext.registerService(myAdapterFactory);
// test adaption
MyClass object = resource.adaptTo(MyClass.class);
// cleanup after unit test
MockSling.clearAdapterManagerBundleContext();
14
Sling Mocks: Sling Helper, Response, request
org.apache.sling : org.apache.sling.testing.sling-mock
SlingScriptHelper scriptHelper = MockSling.newSlingScriptHelper();
SlingHttpServletRequest request = scriptHelper.getRequest();
// get service
MyService object = scriptHelper.getService(MyService.class);
MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);
request.setQueryString("param1=aaa&param2=bbb");
request.setResource(resourceResolver.getResource("/content/sample"));
MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();
15
Sling Mocks: Create or Import test data
org.apache.sling : org.apache.sling.testing.sling-mock
ContentLoader contentLoader = new ContentLoader(resolver);
contentLoader.json("/sample-data.json", "/content/sample/en");
// Import binary data from file in classpath
ContentLoader contentLoader = new ContentLoader(resolver);
contentLoader.binaryFile("/sample-file.gif", "/content/binary/sample-file.gif");
ContentBuilder contentBuilder = new ContentBuilder(resolver);
contentBuilder.resource("/content/test1", ImmutableMap.<String, Object>builder()
.put("prop1", "value1").put("prop2", "value2").build());
16
Sling Mocks: OSGi
org.apache.sling : org.apache.sling.testing.osgi-mock
Supports:
1. Bundle, BundleContext and ComponentContext objects and navigate between them;
2. Register services;
3. Reading metadata from /OSGI-INF/<pid>.xml and from /OSGI-INF/serviceComponents.xml;
4. Apply service configuration provided in unit test and from SCR metadata;
5. Inject dependencies - static and dynamic;
6. Call lifecycle methods for activating, deactivating or modifying;
7. Service and bundle listener implementation;
8. Mock implementation of LogService which logs to SLF4J in JUnit context;
9. Mock implementation of EventAdmin which supports EventHandler services;
17
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
public class OSGiExampleTest {
@Rule
private 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);
}
}
18
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
BundleContext bundleContext = MockOsgi.newBundleContext();
BundleContext bundleContext = MockOsgi.newComponentContext(properties,
ImmutableMap.<String, Object>of("prop1", "value1"));
// register service
bundleContext.registerService(MyClass.class, myService, properties);
// get service instance
ServiceReference ref = bundleContext.getServiceReference(MyClass.class.getName());
MyClass service = bundleContext.getService(ref)
19
Sling Mocks: OSGi Example
org.apache.sling : org.apache.sling.testing.osgi-mock
// get mock bundle context
BundleContext bundleContext = MockOsgi.newBundleContext();
// create service instance manually
MyService testedService = new MyService();
// inject dependencies
MockOsgi.injectServices(testedService, bundleContext);
// activate service
MockOsgi.activate(testedService, props);
// test service...
// deactivate service
MockOsgi.deactivate(testedService);
20
WCM.IO
wcm.io : io.wcm.testing.aem-mock
21
WCM.IO
wcm.io : io.wcm.testing.aem-mock
Supports:
1. Mocked OSGi, JCR and Sling environment provided by the Apache Sling project;
2. Implementation of AEM API level (PageManager, Page, Template, ComponentManager,
Component, TagManager, Tag, Designer, Asset and Rendition);
3. JUnit rule AemContext;
4. Full support for Sling Models;
5. Setting run modes;
6. Layer adapter factory;
Not supported:
1. Other parts of the AEM API;
22
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public class ExampleTest {
@Rule
public final AemContext context = new AemContext();
@Test
public void testSomething() {
Resource resource = context.resourceResolver().getResource("/content/sample/en");
Page page = resource.adaptTo(Page.class);
// further testing
}
}
23
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public class ExampleTest {
@Rule
public final AemContext context = new AemContext();
@Test
public void testSomething() {
context.pageManager().create("/content/sample/en", "test1",
"/apps/sample/templates/homepage", "title1");
//…
Page page = context.pageManager().getPage("/content/sample/en");
Template template = page.getTemplate();
Iterator<Page> childPages = page.listChildren();
// further testing
context.pageManager().delete(page, false);
}
}
24
WCM.IO: Example
wcm.io : io.wcm.testing.aem-mock
public final AemContext context = new AemContext(new SetUpCallback());
private static final class SetUpCallback implements AemContextCallback {
@Override
public void execute(final AemContext context) throws PersistenceException, IOException {
// application-specific services for unit tests
context.registerService(AdapterFactory.class, new AppAdapterFactory());
context.registerService(new AemObjectInjector());
// import sample content
context.contentLoader().json("/sample-content.json", "/content/sample/en");
// set default current page
context.currentPage("/content/sample/en");
}
25
Q&A?

Contenu connexe

Tendances

Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered HarmfulBrian Gesiak
 
NoSQL and JavaScript: a love story
NoSQL and JavaScript: a love storyNoSQL and JavaScript: a love story
NoSQL and JavaScript: a love storyAlexandre Morgaut
 
SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8Ben Abdallah Helmi
 
50 new features of Java EE 7 in 50 minutes
50 new features of Java EE 7 in 50 minutes50 new features of Java EE 7 in 50 minutes
50 new features of Java EE 7 in 50 minutesAntonio Goncalves
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to missAndres Almiray
 
Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Christopher Batey
 
Building stable testing by isolating network layer
Building stable testing by isolating network layerBuilding stable testing by isolating network layer
Building stable testing by isolating network layerJz Chang
 
Down to Stack Traces, up from Heap Dumps
Down to Stack Traces, up from Heap DumpsDown to Stack Traces, up from Heap Dumps
Down to Stack Traces, up from Heap DumpsAndrei Pangin
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code genkoji lin
 
JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発Naoto Takai
 
JRuby on Rails and Thread Safety
JRuby on Rails and Thread SafetyJRuby on Rails and Thread Safety
JRuby on Rails and Thread SafetyNaoto Takai
 
Meetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbcMeetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbczznate
 
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"GeeksLab Odessa
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsTimur Shemsedinov
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleAnton Arhipov
 
State of the art - server side JavaScript - web-5 2012
State of the art - server side JavaScript - web-5 2012State of the art - server side JavaScript - web-5 2012
State of the art - server side JavaScript - web-5 2012Alexandre Morgaut
 

Tendances (20)

Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered Harmful
 
NoSQL and JavaScript: a love story
NoSQL and JavaScript: a love storyNoSQL and JavaScript: a love story
NoSQL and JavaScript: a love story
 
SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8
 
50 new features of Java EE 7 in 50 minutes
50 new features of Java EE 7 in 50 minutes50 new features of Java EE 7 in 50 minutes
50 new features of Java EE 7 in 50 minutes
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
 
Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014
 
Drupal 8: Fields reborn
Drupal 8: Fields rebornDrupal 8: Fields reborn
Drupal 8: Fields reborn
 
Building stable testing by isolating network layer
Building stable testing by isolating network layerBuilding stable testing by isolating network layer
Building stable testing by isolating network layer
 
Down to Stack Traces, up from Heap Dumps
Down to Stack Traces, up from Heap DumpsDown to Stack Traces, up from Heap Dumps
Down to Stack Traces, up from Heap Dumps
 
Annotation processing and code gen
Annotation processing and code genAnnotation processing and code gen
Annotation processing and code gen
 
JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発
 
Everything as a code
Everything as a codeEverything as a code
Everything as a code
 
JRuby on Rails and Thread Safety
JRuby on Rails and Thread SafetyJRuby on Rails and Thread Safety
JRuby on Rails and Thread Safety
 
Meetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbcMeetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbc
 
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"
JS Lab`16. Сергей Селецкий: "Ретроспектива тестирования JavaScript"
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
State of the art - server side JavaScript - web-5 2012
State of the art - server side JavaScript - web-5 2012State of the art - server side JavaScript - web-5 2012
State of the art - server side JavaScript - web-5 2012
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 

Similaire à EPAM IT WEEK: AEM & TDD. It's so boring...

RESTFul development with Apache sling
RESTFul development with Apache slingRESTFul development with Apache sling
RESTFul development with Apache slingSergii Fesenko
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample applicationAntoine Rey
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenJoshua Long
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to JavascriptAmit Tyagi
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++Amazon Web Services
 
Build a Node.js Client for Your REST+JSON API
Build a Node.js Client for Your REST+JSON APIBuild a Node.js Client for Your REST+JSON API
Build a Node.js Client for Your REST+JSON APIStormpath
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiecturesIegor Fadieiev
 
A Series of Fortunate Events: Building an Operator in Java
A Series of Fortunate Events: Building an Operator in JavaA Series of Fortunate Events: Building an Operator in Java
A Series of Fortunate Events: Building an Operator in JavaVMware Tanzu
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Roberto Franchini
 
Developing a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayDeveloping a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayJacob Park
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with SpringJoshua Long
 
Avoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAvoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAnkit Agarwal
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long jaxconf
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascriptDoeun KOCH
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Node Summit 2018 - Optimize your Lambda functions
Node Summit 2018 - Optimize your Lambda functionsNode Summit 2018 - Optimize your Lambda functions
Node Summit 2018 - Optimize your Lambda functionsMatt Lavin
 

Similaire à EPAM IT WEEK: AEM & TDD. It's so boring... (20)

Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
RESTFul development with Apache sling
RESTFul development with Apache slingRESTFul development with Apache sling
RESTFul development with Apache sling
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample application
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++
 
Testing with Node.js
Testing with Node.jsTesting with Node.js
Testing with Node.js
 
Build a Node.js Client for Your REST+JSON API
Build a Node.js Client for Your REST+JSON APIBuild a Node.js Client for Your REST+JSON API
Build a Node.js Client for Your REST+JSON API
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiectures
 
A Series of Fortunate Events: Building an Operator in Java
A Series of Fortunate Events: Building an Operator in JavaA Series of Fortunate Events: Building an Operator in Java
A Series of Fortunate Events: Building an Operator in Java
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
 
Developing a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayDeveloping a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and Spray
 
OpenCMIS Part 1
OpenCMIS Part 1OpenCMIS Part 1
OpenCMIS Part 1
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
 
Avoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAvoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promises
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascript
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Node Summit 2018 - Optimize your Lambda functions
Node Summit 2018 - Optimize your Lambda functionsNode Summit 2018 - Optimize your Lambda functions
Node Summit 2018 - Optimize your Lambda functions
 
Liferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for DevelopersLiferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for Developers
 

Dernier

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 

Dernier (20)

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 

EPAM IT WEEK: AEM & TDD. It's so boring...

  • 1. 1 AEM & TDD It’s so boring… AUGUST 6, 2015
  • 2. 2 Testing AEM as JCR-based Applications JCR testing tools1 Sling API level2 OSGi API level3 AEM application level4 OSGi AEM SLING JCR
  • 3. 3 JCR: Dependency javax.jcr:jcr org.apache.jackrabbit:jackrabbit-core scope: test org.apache.jackrabbit:jackrabbit-jcr-commons scope:test
  • 4. 4 JCR: Example @BeforeClass RepositoryConfig config = RepositoryConfig.create(configStream, TEMP_FOLDER.newFolder().getAbsolutePath()); TransientRepository REPOSITORY = new TransientRepository(config); Credentials credentials = new SimpleCredentials("admin", "admin".toCharArray()); REAL_SESSION = REPOSITORY.login(credentials, "default"); @ClassRule public static TemporaryFolder TEMP_FOLDER = new TemporaryFolder();
  • 5. 5 Apache Sling artifacts Sling testing tools1 JCR Mocks2 Resource Resolver Mocks3 Sling Mocks4 OSGi Mocks5
  • 6. 6 Sling Testing Utilities org.apache.sling : org.apache.sling.commons.testing public class YourTest extends RepositoryTestBase { RepositoryUtil.registerNodeType(getSession(), getClass().getClassLoader().getResourceAsStream("cq.cnd")); Node node = JcrUtil.createPath(“/etc/tags”, SLING_FOLDER, getSession()); }
  • 7. 7 JCR Mocks org.apache.sling : org.apache.sling.testing.jcr-mock Supports: 1. Reading and writing all data (primitive values, arrays, binary data) via the JCR API; 2. Creating any number of nodes and properties (stored in-memory in a hash map); 3. Register namespaces; 4. Queries are supported by setting expected results for a given query; Not supported: 1. Node types are supported in the API, but their definitions and constraints are not applied; 2. Versioning not supported; 3. Transactions not supported; 4. Observation events can be registered but are ignored; 5. Access control always grants access; 6. Exporting/Importing data via document and system views not supported; 7. Workspace management methods not supported;
  • 8. 8 JCR Mocks Example org.apache.sling : org.apache.sling.testing.jcr-mock // get session Session session = MockJcr.newSession(); // get repository Repository repository = MockJcr.newRepository(); // prepare mocked search result List<Node> resultNodes = ImmutableList.of(node1, node2, node3); // return this result for all queries MockJcr.setQueryResult(session, resultNodes); // return this result for a specific query MockJcr.setQueryResult(session, "your query statement", Query.JCR_SQL2, resultNodes);
  • 9. 9 Resource Resolver Mocks org.apache.sling : org.apache.sling.testing.resourceresolver-mock Supports: 1. All read and write operations of the Sling Resource API 2. Mimics transactions using via commit()/revert() methods 3. OSGi events for adding/changing/removing resources 4. The implementation tries to be as close as possible to the behavior of the JCR resource implementation e.g. concerning date and binary handling Not supported: 1. Authentication not supported ("login" always possible with null authentication info) 2. Querying with queryResources/findResources not supported (always returns empty result set) 3.Sling Mapping is not supported 5. Resolving resource super types
  • 10. 10 Sling Mocks org.apache.sling : org.apache.sling.testing.sling-mock Supports: 1. Reading and writing resource data using the Sling Resource API; 2. Backed by a mocked or real Jackrabbit JCR implementation; 3. Resource-JCR mapping or non-JCR mock implementation; 4. Registering adapter factories and resolving adaptions; 5. SlingScriptHelper mock implementation; 6. SlingHttpServletRequest and SlingHttpServletRequest; 7. MockModelAdapterFactory and MimeTypeService; Not supported: 1. It is not possible (nor intended) to really execute sling components/scripts and render their results, because the goal is to test supporting classes in Sling context, not the sling components/scripts themselves;
  • 11. 11 Sling Mocks: Example org.apache.sling : org.apache.sling.testing.sling-mock @Rule public final SlingContext context = new SlingContext(); @Test public void testSomething() { Resource resource = context.resourceResolver().getResource("/content/sample/en"); // further testing } RESOURCERESOLVER_MOCK1 JCR_MOCK2 NONE3 JCR_JACKRABBIT4 JCR_OAK5new SlingContext( )
  • 12. 12 Sling Mocks: Example org.apache.sling : org.apache.sling.testing.sling-mock // get a resource resolver ResourceResolver resolver = MockSling.newResourceResolver(); // get a resource resolver factory MockSling.newResourceResolverFactory(ResourceResolverType.RESOURCERESOLVER_MOCK); // get a resource resolver backed by a specific repository type ResourceResolver resolver = MockSling.newResourceResolver(ResourceResolverType.JCR_MOCK);
  • 13. 13 Sling Mocks: Adapter Factories org.apache.sling : org.apache.sling.testing.sling-mock // register adapter factory BundleContext bundleContext = MockOsgi.newBundleContext(); MockSling.setAdapterManagerBundleContext(bundleContext); bundleContext.registerService(myAdapterFactory); // test adaption MyClass object = resource.adaptTo(MyClass.class); // cleanup after unit test MockSling.clearAdapterManagerBundleContext();
  • 14. 14 Sling Mocks: Sling Helper, Response, request org.apache.sling : org.apache.sling.testing.sling-mock SlingScriptHelper scriptHelper = MockSling.newSlingScriptHelper(); SlingHttpServletRequest request = scriptHelper.getRequest(); // get service MyService object = scriptHelper.getService(MyService.class); MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver); request.setQueryString("param1=aaa&param2=bbb"); request.setResource(resourceResolver.getResource("/content/sample")); MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();
  • 15. 15 Sling Mocks: Create or Import test data org.apache.sling : org.apache.sling.testing.sling-mock ContentLoader contentLoader = new ContentLoader(resolver); contentLoader.json("/sample-data.json", "/content/sample/en"); // Import binary data from file in classpath ContentLoader contentLoader = new ContentLoader(resolver); contentLoader.binaryFile("/sample-file.gif", "/content/binary/sample-file.gif"); ContentBuilder contentBuilder = new ContentBuilder(resolver); contentBuilder.resource("/content/test1", ImmutableMap.<String, Object>builder() .put("prop1", "value1").put("prop2", "value2").build());
  • 16. 16 Sling Mocks: OSGi org.apache.sling : org.apache.sling.testing.osgi-mock Supports: 1. Bundle, BundleContext and ComponentContext objects and navigate between them; 2. Register services; 3. Reading metadata from /OSGI-INF/<pid>.xml and from /OSGI-INF/serviceComponents.xml; 4. Apply service configuration provided in unit test and from SCR metadata; 5. Inject dependencies - static and dynamic; 6. Call lifecycle methods for activating, deactivating or modifying; 7. Service and bundle listener implementation; 8. Mock implementation of LogService which logs to SLF4J in JUnit context; 9. Mock implementation of EventAdmin which supports EventHandler services;
  • 17. 17 Sling Mocks: OSGi Example org.apache.sling : org.apache.sling.testing.osgi-mock public class OSGiExampleTest { @Rule private 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); } }
  • 18. 18 Sling Mocks: OSGi Example org.apache.sling : org.apache.sling.testing.osgi-mock BundleContext bundleContext = MockOsgi.newBundleContext(); BundleContext bundleContext = MockOsgi.newComponentContext(properties, ImmutableMap.<String, Object>of("prop1", "value1")); // register service bundleContext.registerService(MyClass.class, myService, properties); // get service instance ServiceReference ref = bundleContext.getServiceReference(MyClass.class.getName()); MyClass service = bundleContext.getService(ref)
  • 19. 19 Sling Mocks: OSGi Example org.apache.sling : org.apache.sling.testing.osgi-mock // get mock bundle context BundleContext bundleContext = MockOsgi.newBundleContext(); // create service instance manually MyService testedService = new MyService(); // inject dependencies MockOsgi.injectServices(testedService, bundleContext); // activate service MockOsgi.activate(testedService, props); // test service... // deactivate service MockOsgi.deactivate(testedService);
  • 21. 21 WCM.IO wcm.io : io.wcm.testing.aem-mock Supports: 1. Mocked OSGi, JCR and Sling environment provided by the Apache Sling project; 2. Implementation of AEM API level (PageManager, Page, Template, ComponentManager, Component, TagManager, Tag, Designer, Asset and Rendition); 3. JUnit rule AemContext; 4. Full support for Sling Models; 5. Setting run modes; 6. Layer adapter factory; Not supported: 1. Other parts of the AEM API;
  • 22. 22 WCM.IO: Example wcm.io : io.wcm.testing.aem-mock public class ExampleTest { @Rule public final AemContext context = new AemContext(); @Test public void testSomething() { Resource resource = context.resourceResolver().getResource("/content/sample/en"); Page page = resource.adaptTo(Page.class); // further testing } }
  • 23. 23 WCM.IO: Example wcm.io : io.wcm.testing.aem-mock public class ExampleTest { @Rule public final AemContext context = new AemContext(); @Test public void testSomething() { context.pageManager().create("/content/sample/en", "test1", "/apps/sample/templates/homepage", "title1"); //… Page page = context.pageManager().getPage("/content/sample/en"); Template template = page.getTemplate(); Iterator<Page> childPages = page.listChildren(); // further testing context.pageManager().delete(page, false); } }
  • 24. 24 WCM.IO: Example wcm.io : io.wcm.testing.aem-mock public final AemContext context = new AemContext(new SetUpCallback()); private static final class SetUpCallback implements AemContextCallback { @Override public void execute(final AemContext context) throws PersistenceException, IOException { // application-specific services for unit tests context.registerService(AdapterFactory.class, new AppAdapterFactory()); context.registerService(new AemObjectInjector()); // import sample content context.contentLoader().json("/sample-content.json", "/content/sample/en"); // set default current page context.currentPage("/content/sample/en"); }

Notes de l'éditeur

  1. Всем привет! Рад что вы смогли выкроить время для меня, да еще в добавок после рабочего дня. Спасибо вам, мне не будет так скучно говорить. А то бы сидел сам и рассказывал Диме, коорый бы меня фоткал. Тема у меня про СКУКУ. Тема довольно заезженная на конференциях – юнит тесты, TDD, бла, бла, бла и прочее... Давайте писать ровнее, стройнее и более правильно. Я не буду напрягать рассказам о том как хорошо работать через TDD. Я сам не следую постоянно этой методологии и иногда лажаю. Пишу код и только потом тесты. Все мы не без греха. Но я точно знаю, что я в них верю. Вот скажите мне – что для вас юнит тесты? (спросить пару человек). Для меня, это в первую очередь – уверенность, что в 80-90 % случаев после внесения изменений в код и при прохождении тестов и срабатывании теста на мою логику я могу спокойно уйти с работы быть уверенным, что СКОРЕЕ ВСЕГО ничего не поломал. Я прямо подчеркнул эти слова - СКОРЕЕ ВСЕГО. Но даже с этим скорее всего мне спиться спокойней. Ради этого самого спокойствия я поддерживаю тесты и даже переписываю полностью тесты на класс, когда нахожу на это время. А теперь про цель моей презентации. Она проста – рассказать вам что то новое и понять это самому немного глубже, ведь когда пытаешься кому то рассказать что то , понимаешь это лучше. И хотя тема немного не такая, как было заявлено, я смело поменял её, потому что нашел что то новое и хотел про это рассказать. Т.е. не только контент репозитории, но и AEM как таковой. Посмотрите сюда – (открыть проект и показать пример из пакета wrongmock – медленно скролить). Что тут у нас? А…. А ведь это из реального проекта… Как часто вы видите такие тесты? Это очень, очень трудозатратно такое писать. Иногда руки просто опускаються…
  2. И конечно, глядя на такое мне хотелось найти пути уменьшить оверхэд при написании тестов. Убрать эти простыни моков, ну или хотя бы уменьшить их. Я решил посмотреть, что у нас есть сейчас на проекте и что можно использовать для того, что бы уменьшить количество времени затрачиваемого на написание тестов. При всём этом, проблему усиливает то, что у нас классы зачастую используют разные уровни API - JCR, Sling и AEM. Все видели классы разные методы которого работаю как с нодами так и с ресурсами SLING фреймворка. Для того что бы написать хорошие тесты нам надо чётко определять, с каким уровнем API мы работаем в классе и при необходимости отрефакторить класс. Давайте поёдем снизу вверх и рассмотрим, что мы можем использовать для своих нужд. К счастью, у нас не сильно большой выбор и потому я пошел по одной линейки самых лучших библиотек.
  3. Итак, давайте начнём с самого нижнего уровня - JCR репозитория. Часто мы ограничиваемся только библиотекой Mockito и иногда ИМЕЕТ смысл использовать ТОЛЬКО её. Но часто, нам надо тестировать не просто вызовы методов репозитория, а манипуляции с данными в репозитории. Просто вызов методов что нам даст то? Ну вроде как что то сделали с нодой, выставили свойство, поменял что то. А если мы вызвали еще один метод и выставили новое свойство? Проверили, что вызвалось свойство ноды с любой строкой как имя свойства и любой строкой как значение? А если мы забыли замокать метод? Мокито нам вообще не даст никакой информации. А методы которые складывают данные в репозиторий по определённой логике ? Так что же делать ? – Создавать реальные данные и тестировать логику манипуляции с данными. Многим, если не всем известен старый знакомый класс – TransientRepository из ядра бибилиотеки JCR. Что может быть лучше, чем реальный репозиторий для тестирования логики работы с репозиторием? TransientRepository стартует репозиторий после первого логина и останавливает его когда последняя сессия завершает свою работу. Репозиторий сам по себе стартует в памяти, что позволяет ему работать довольно быстро, но несмотря на это репозиторий создаёт структуру файлов на диске и при сохранении сессии сохраняет все данные в эту структуру. Конечно, работа с диском нежелательна, но это так называемый tradeoff. Что мы должны учитывать в нашем тесте ? Для того, что бы уменишить время обращения к диску, мы можем покладывать файл конфигурации, который иначе будет создаваться и записываться на диск при каждом старте в каждом тесте. Мы будем обязаны подкладывать CND файл с моделями данных нашего репозитория. Нам нужна будет административная сессия для создания тестовых данных и их очистки репозитория в ПРЕ / ПОСТ методах тест класса. На слайде я указал все зависимости которые будут нужны. Это сама спецификация JCR API, её имплементация Jackrabbit и Jackrabbit commons для более комфортной работе с репозиторием.
  4. Я написал тест и постарался учесть все моменты и обьеденить лучшие практики в тесте. Основные точки класса которые нужно рассмотреть это временная директория, для того, что бы множественные запуски тестов не аффектили друг друга, если очистка репозитория проввалиться. Для этого можно использовать класс TemporaryFolder из бибилиотеки junit вместе с аннотацией ClassRule. Папочка созданная таким образом перед тестом будет уничтожаться после завершения тестов самим JUnit. Далее, можно создать конфигурационный файл репозитория. Конечно, он может создаваться автоматически, но почему бы не попробовать создать свой и использовать его для всех репозиториев ? Достаточно подложить его в ресурсы и использовать каждый раз. Далее, нам необходимы параметры доступа для административной сессии которую и будем по возможности использовать в тестах. После этого, необходимо загрузить CND файл, если он нам необходим. Все эти приготовления должны выполнятся в методе помеченной аннотацией BeforeClass для того, что бы не делать этого перед каждым тест методом. После этого в метода @Before и @After мы можем создавать структуру нод для тестирования и удалять их. После тестов, необходимо очистить тестовые данные для последующих тестов. С временнай директория всё просто - она будет очищена Junit в ином случае необходимо сделать это вручную. В методе помеченном аннотицией @AfterClass необходимо завершить сессию. JUNit сам позаботится о том, что бу удалить репозиторий с диска при любом исходе тестов – провалятся они или нет. Открыть и показать файл DefaultFeedGenerationPersisterTest. В принципе это наверно единственный подход для тестирования логики классов работающих с репозиторием.
  5. Но мы часто обращаемся к хранилищу данные через API фреймворка Sling для которого те же ноды представлены в виде ресурсов. При этом мы можем адаптировать ресурсы к нодам и работать уже с ними. Это не совсем правильный подход, и это лично моё мнение, он обусловен не всегда удобной функциональность Sling или незнанием и неумением с ним работать. А часто и не желанием искать функционал, а работе по принципу – буду делать так, как знаю и ладно. Имитация двух уровней API еще более усложняют имитацию фреймворков и логики работы с ними. Но, к счастью, есть бибилиотеки которые много могут сделать за нас. В данном случае мы будем использовать бибилотеки написанные именно для тестов. При этом для нас есть целый ряд (5 штук) отдельных библиотек для тестов различного типа и уровня. Я их отсортировал примерно по возрастанию сложности. Первая библиотека Sling Testing Tools загружаеться как бандл предоставляет инструменты для следующих случаев: Запуск Unit тестов в OSGi контейнере. Наличие Sling фреймворка не обязателено и бандл может быть использован в различных реализациях OSGi контейнера, не только Apache Felix. Далее запуск тестов в запущенном инстансе Sling фреймворка. Запуск интеграционных тестов через HTTP вызовы как во время сборки так и отдельными командами в рабочем энве. JCR Mocks - библиотека которая облегчает нам написание тестов на репозиторий. Resource Resolver Mock – имитирует дерево ресурсов Sling фреймворка. Sling Mock - обладает более шировкими возможностями чем преведущая бибилотека и позволяет тестировать классы которые используют Sling API OSGi mocks позволяет тестировать классы использующие OSGi API. Я затрону ключевые моменты каждой библиотеки.
  6. Sling testing tools предоставляет набор классов моков для различных уровней нашего приложения. В частности, для нас будет интересен базовый класс RepositoryTestBase ( смотрим ImprovedBrandsDAOTest) который позволяет вынести некоторые затраты на создание репозитория из наших тестов. Остальное для нас не столь важно. Давайте посмотрим на пример в классе ImprovedBrandsDAOTest
  7. Следующая бибилиотека JCR Mock уже имитирует работу с JCR API в нашем тестируемом классе. Т.е. логику работы с реальным репозиторием, но при этом реального репозитория не поднимаеться. Как всегда, у нас есть то, что поддерживаеться и то, что не поддерживаться Данная реализация поддерживает запись и чтение даннных. Создание любого количества нод и свойств в памяти. (по сути в мапе). Регистрация пространств имён. Частичная поддержка запросов через указание того какой результат будет возвращён. Не поддерживаеться Типы нод поддерживаються, но их структура или огрничения нет. Нет версионирования. Транзакции не поддериваються. Слушатели событий могут быть зарегестрированы, но выполнятся не будут. Не поддержки уровней доступа. Экспорт или импорт данных из документа или систему не поддерживается. Управление workspace не поддерживается.
  8. И рассмотрим совсем простенький примерчик. Всё взаимодействие происходит через обьект фабрику MockJcr, которая позволяет получать Моки различных обьектов. Например, сессии и репозитория. Тестовый репозиторий пустой и содержит только корневую ноду. Используя методы работы с репозиторием (утильные классы), мы можем создавать структуру необходимую для тестов. Если возникает необходимость тестировать запросы, то мы просто указываем предполагаемое значение которое будет возвращено. Либо, как альтернатива, можно указать каллбэк метод, который позволит динамически настроить возвращаемый набор нод в зависимости от переданного выражения.
  9. Следующая библиотека позволяет создать Мок структуру виртуального дерева ресурсов из которой можно получить ResourceResolver и ResourceResolverFactory. Структура под капотом Sling Resource API использует обычную мапу в памяти для хранения всех данных. Эта структура поддерживает транзакционность используя методы commit и revert. Есть поддержка OSGi событий для добавления, изменения или удаления ресурсов. Эта имплементация написана так, что бы максимально близко имитировать поведение JCR реурсов, включая работу с датами и бинарными данными. Какой функционал не поддерживается: Аутонтефикация не поддерживается. Всегда имитируеться логин в репозиторий. Механизм запросов методами queryResources и findResources не поддерживается всегда возвращается пустой набор). Sling маппинг ресурсов на другие пути не поддеривается. Нет поддержкки наследования типов. Т.е. по сути при обычноей работе с ресурсами, нам этой бибилотечки достаточно. Давайте откроем класс ImprovedAgainJcrBrandsDAOImplTest метод shouldGetAllBrands()
  10. Следуящая у нас большая библиотека которая затрагивает не только ресурсы, но и прочие аспекты работы Sling фреймворка. Используя эту библиотеку мы получаем дополнительно: Всё возможности преведущей библиотеки по работе с деревом ресурсов. НО!! Мы можем выбирать какой тип репозитория использовать в тестах. Про это немного далее. Библиотека базирована на различных имплементациях репозитория, как реального так и виртуального. Внутренний ресурс провайдер позволяет мапить ресурсы на JCR, если это необходимо. При этом можно использовать не JCR реализацию основанную на пакете бибилотеке ResourceResolver Mock который мы рассмотрели ранне. Мы можем регистрировать свои адаптеры и тестировать их. Реализация потоко безопасна , потому юнит тесты могу быть запущены паралельно. Мок SlingScriptHelper позволяет получить доступ к запросу, ответу и поддерживает получение OSGi сервиса из псевдо OSGi контейнера. Обьекты SlingHttpServletRequest и SlingHttpServletRequest позволяют устанавливать параметры запросы. В самом фреймворке реализованы некоторые псевдо сервисы, типа MockModelAdapterFactory и MimeTypeService Дополнительно добавлена правило SlingContext, которая позволяет интегрироваться в Junit. ContentLoader поддерживает импорт данных из JSON файлов и бинарных данных в нашу иерархию ресурсов. ContentBuilder позволяет легко создавать структуру тестовых данных. Что не поддерживается: Реальное исполнение скриптов Sling фреймворка и рэндер результатов, потому как основная цель всё таки протестировать классы в контексе.
  11. Небольшой пример кода для вас. Создание обьект контекста и получение ресурс резолвера. Но, как я упомянул, мы можем играться с типами контекста. В зависимости от того какой тип мы выберем разные типы репозиториев будут доступны нам. По умолчанию используеться тип: RESOURCERESOLVER_MOCK. Мы указываем что хотим эмулировать дерево ресурсов в памяти как это делает преведущая библиотека. Быстрое и простое решение. JCR_MOCK создаёт дерево ресурсов и имитацию реаозитория которая базируется на JCR Mocks реализации, рассмотреной ранее. NONE – использует реализацию Sling Resource Factory без ResourceProvider ов. Необходимо регистрировать свои провайдеры которые будут предоставлять данные. Т.е. свои реализации интерфейса ResourceResolverFactory и ResourceResolver. Полезно только, если мы используеться другое хранилище данных. JCR_JACKRABBIT – использует реальный репозиторий из пакета sling.commons.testing, т.е. тот самый TransientRepository который мы рассматривали ранее. JCR_OAK – использует реальный репозиторий, только уже имплементацию Oak базирующийся на самой простой реализации MemoryNodeStore, которая хранит репоизторий в памяти. Все плюшки реального репозитория дают нам полный контроль над тестированием данных, хотя и занимает несколько секунд (миллисекунд?) для поднятия репозитория для каждого теста. При использовании реальных репозиториев необходимо помнить, что они не очищаются для каждого теста, потому необходимо это контролировать. Опять таки регистрация типов нод лежит на вас. Обе эти имплементации имею набор дополнительных зависимостей , которые надо подключить. Открыть ImprovedJcrProductsDAOImplTest
  12. И опять таки мы можем использовать обьект фактори для получения нужных нам обьектов. На этом примере – резолвер обычный и резолвер с типом. После того, как выбрали какой репозиторий вы хотите использовать для тестов, создаём его и создаём тестовые данные. Посмотрим как я это делаю в ImprovedAgainAndAgainJcrBrandsDAOImplTest для примера
  13. Из дополнительных плюшек библиотеки, мы можем подключать свои классы адаптеры (пир этом вариант адаптации к моку тоже следует рассматривать) и тестировать их работу в контексте фреймворка.
  14. Если наш класс получает OSGi сервис, то мы можем зарегестрировать его через BundleContext интерфейс реализация которого в JCR Mock пакете. Но, мы можем использовать обьект SlingScriptHelper через фабричный метод класса MockSling который предоставляет экземпляры реквеста, респонса и контекста бандла для тестирования.
  15. Еще одна из плюшек, которую мы видели уже – обьекты для быстрого создания тестового контента через импорт данных из JSON файла. Обьект лоадер достпен в  SlingContext через метод load(). При необходимости можно загрузить бинарные данные если мы манипулируем стримами в нашем классе. Данные будут сохранены в стандартых нодах типа nt:file/nt:resource или nt:resource. Напрмер этот код создаёт новый ресурс /content/binary/sample-file.gif (и, все вышележащие ресурсы) и импортирует бинарные данные в jcr:content дочернюю ноду. Второй обект – ContentBuilder для быстрого создания ресурсов вручную через методы билдера. Обьект билдер достпен в  SlingContext через метод build().
  16. И последняя библиотека позволяет использовать мок обьект OSGi контейнер. Т.е типа бандл обьект, конекст бандла и взаимодействие между ними. В итоге регистрируя свои сервисы мы можем тестировать получение ссылок на них и работу с ними. Бибилиотека позволяе читать и разбирать метаинформацию по сервисам из XML файлов что позволяет применять конфигурацию на сервис. Поддерживает внедрение зависимостей на основе аннотаций, как статичискую, так и динамическую. Наш псевдо контейнер вызывает методы активации, модификации и деактивации компонента среды OSGi. Возможно регистрировать слушатели на сервисы и бандлы. Контейнер содержит моковую имплментацию LOGService который логирует информацию через SLF4J в контексте Junit тестов и моковую имплементацию EventAdmin а который поддерживает регистрацию EventHandler ов сервисов.
  17. Простенький пример использовани конекста. Создание нового контекста, добавление и активация нового класса и получение экземпляра сервиса.
  18. При использовании фабричного метода класса MockOsgi позволяет получить различные обьекты моки – бандл контекст, компонент контекст и прочее. Так же поддерживаеться симуляция регистрации сервисов в контексте.
  19. При работе с конекстом необходим быть уверенным, что регистрируешь сервисы в правильном порядке по цепочке зависимостей. Только динамические ссылки будут автоматическо обработаны в не зависимости от порядка регистрации классов. Метод injectServices, activate и deactivate могут работать правильно только когда метаданные в XML файле найдены в текущем пути загрузки классов в OSGI-INF директории. Как вы знете они генерируються автоматически плагином Maven SCR и выложены по правильно пути другим плагином, типа assemble.
  20. И вот надо идти глубже, вернее подниматься в наших абстракциях. Тестировать работу с AEM.И здесь нам может помочь бибилотека WCM.IO.
  21. Что она поддерживате ? The mock implementation supports: Access to mocked OSGi, mocked JCR and mocked Sling environment provided by the Apache Sling project. Т.е. по сути ко всему, что мы рассматривали ранее. Implementation of AEM WCM API objects PageManager, Page, Template, ComponentManager, Component, TagManager, Tag, Designer Implementation of AEM DAM API objects Asset and Rendition JUnit rule AemContext for easy access to all context objects and registering adapter factories and OSGi services Full support for Sling Models Setting run modes Layer adapter factory The following features are not supported: Other parts of the AEM API
  22. Простенький пример. Всё наше взаимодействие происходит через обьект AemContext который создаётся JUnit правилом. Обьект сам заботится об инициализациях и очистки для того что бы наши тесты проходили чисто и независимо. И если надо, паралельно. Мы можем комбинировать юнит тесты с аннотацией @RunWith и фреймворком Mockito. Класс AemContext предоставляет следующие обьекты и функционал, которые он, правильно, берёт из прочих библиотек рассмотренных ранее и наследует весь их фунционал. OSGi Component Context, OSGi Bundle Context, Sling Resource Resolver, Sling Request, Sling Response, Sling Script Helper Registering OSGi services, Registering adapter factories, Accessing JSON Importer
  23. А вот и простой пример использования AEM API методов в Юнит тестах
  24. При построении юнит тестов для приложения мы обычно используем какие либо специфические задачи, такие как регистрация сервисов, адапетров и импорт контента. Для того, что бы сделать тесты более чистыми мы можем использовать каллбэк классы в которых будет реализован необходимый функционал.
  25. Вот и всё. Спасибо!