Testing Fuse Fabric with Pax Exam

Post on 02-Jul-2015

433 views 1 download

Transcript of Testing Fuse Fabric with Pax Exam

Testing Fuse Fabric with

Pax ExamBrought to you by / Henryk Konsek @hekonsek

This talk1. Our goals2. Pax Exam3. Case studies

1. Our goals

Our problemsOSGi ;)it works on my computer aka responsibility ping-pongcreating repeatable middleware proof of concepts is difficultgoing production without proper testing

Our goalsrepeatable tests of middleware - infracodingOSGi issues detected and fixed as soon as possibleeducated customers sending us runnable and repeatableexamples

2. Pax Exam

What is Pax ExamJUnit friendly framework for running tests in real KarafcontainersExam deploys JUnit test case as a bundleif the bundle can be successfully tested with the Exam, thenit can be successfully deployed to Karaf

Exam hello world!Project structure

my-project my-project-services my-project-routes ... my-project-bundle my-project-itest

Exam hello world!JUnit class

@RunWith(PaxExam.class)public class MyKarafTest extends Assert {

@Inject MyOsgiService myOsgiService;

@Configuration public Option[] configuration() { ... }

@Test public void shouldReturnResponse() { ... }

}

Exam hello world!Karaf configuration

@Configurationpublic Option[] configuration() { return new Option[]{ karafDistributionConfiguration() .frameworkUrl( maven().groupId("org.apache.karaf").artifactId("apache-karaf") .type("zip").version("2.3.3")). karafVersion("2.3.3").name("Apache Karaf") .unpackDirectory(new File("target/pax")) .useDeployFolder(false), keepRuntimeFolder(), configureConsole().ignoreLocalConsole().ignoreRemoteShell(),

mavenBundle().groupId("com.example").artifactId("my-project-bundle"). versionAsInProject()};}

Exam hello world!Testing OSGi service

@RunWith(PaxExam.class)public class MyKarafTest extends Assert {

@Inject MyOsgiService myOsgiService;

@Configuration public Option[] configuration() { ... }

@Test public void shouldReturnResponse() { assertEquals("Hello!", myOsgiService.helloWorld()); }

}

Exam hello world!Testing OSGi Camel service

@RunWith(PaxExam.class)public class MyDeployedCamelTest extends Assert {

@Inject CamelContext camelContext;

@Configuration public Option[] configuration() {...}

@Test public void shouldReturnResponse() { String response = camelContext.createProducerTemplate(). requestBody("jms:queue", "msg", String.class); assertEquals("Hello!", response); }

}

3. Case studies

Case #1: Hello world!Arm your POM

<repositories> <repository> <id>jboss-fuse-ea</id> <url>https://repository.jboss.org/nexus/content/groups/ea</url> </repository></repositories>

Engineering guys deploy here.

<properties> <fabric-version>1.0.0.redhat-340</fabric-version></properties>

Pick up some bleeding edge yet stable version of Fabric testAPI.

Case #1: Hello world!Arm your POM

<dependency> <groupid>io.fabric8</groupid> <artifactid>fabric8-karaf</artifactid> <version>${fabric-version}</version> <type>zip</type></dependency>

Download Fabric distribution.

<dependency> <groupid>io.fabric8.itests</groupid> <artifactid>fabric-itests-common</artifactid> <version>${fabric-version}</version></dependency>

Include Fabric test API (and nothing more!).

Case #1: Hello world!Tested Camel route

public class NettyHttpRoute extends RouteBuilder {

@Override public void configure() throws Exception { from("netty-http:http://localhost:18080/"). setBody().constant("Hello world!"); }

}

Case #1: Hello world!Base test class

import io.fabric8.itests.paxexam.support.FabricTestSupport;...@RunWith(JUnit4TestRunner.class)@ExamReactorStrategy(AllConfinedStagedReactorFactory.class)public class SimpleFabricTest extends FabricTestSupport {

@Configuration public Option[] config() { return new Option[]{ new DefaultCompositeOption(fabricDistributionConfiguration()), mavenBundle("commons-io", "commons-io").versionAsInProject() }; } ...

}

almost no config? Buy Ioannis a beer for creating theFabricTestSupport ;)yeah, this is the old and ugly Pax Exam 2.x API...you need to configure everything you use in the test bundle

Case #1: Hello world!Deploying Camel route

import static java.lang.System.err;

@Testpublic void shouldCreateCamelRouter() throws Exception { err.println(executeCommand("fabric:create -n")); err.println(executeCommand("fabric:profile-create " + "--parents feature-camel netty-http-server")); err.println(executeCommand("fabric:profile-edit " + "--features camel-netty-http netty-http-server")); err.println(executeCommand("fabric:profile-edit --bundles " + "mvn:com.example/my-project-bundle/1.0-SNAPSHOT netty-http-server"));

ContainerBuilder.create(). withName("router-container").withProfiles("netty-http-server"). assertProvisioningResult().build(); // ... assertions}

String output = executeCommand("some:karafCommand");assertProvisioningResult == block until container is ready

Case #1: Hello world!Testing deployed route

@Testpublic void shouldCreateCamelRouter() throws Exception { // ... creating container

InputStream inputStream = new URL("http://localhost:18080/").openStream(); String response = IOUtils.toString(inputStream); assertEquals("Hello world!", response);}

a poor-man's HTTP client

Case #1: Hello world!User friendly output

fabric:create -nUsing specified zookeeper password:admin

fabric:profile-create --parents feature-camel netty-http-serverfabric:profile-edit --features camel-netty-http netty-http-serverAdding feature:camel-netty-http to profile:netty-http-server version:1.0

fabric:profile-edit --bundles ... netty-http-server

Adding bundle:mvn:... to profile:netty-http-server version:1.0Waiting for containers: [ router-container1 ] to successfully provisionContainer:router-container1 Alive:false Status: SSH URL:nullContainer:router-container1 Alive:true Status:analyzing SSH URL:...Container:router-container1 Alive:true Status:downloading SSH URL:...Container:router-container1 Alive:true Status:finalizing SSH URL:...Container:router-container1 Alive:true Status:success SSH URL:...

output partially omitted (SSH address!)very similar to the output from the real Karaf session

Case #2: Hacking childcontainers with SSH

Container container = (Container) create().withName("router-container"). withProfiles("netty-http-server"). assertProvisioningResult().build().iterator().next();

String[] containerSshUrl = container.getSshUrl().split(":");String containerHost = containerSshUrl[0];String containerPort = containerSshUrl[1];

String bundlesOnContainer = executeCommand(format( "ssh -l %s -P %s -p %s %s osgi:list", "admin", "admin", containerPort, containerHost));

assertTrue(bundlesOnContainer.contains("camel-netty-http"));

running Karaf container can be accessed via SSH clientwe can execute any remote Karaf command via ssh

Case #3: Fabric Mastercomponent test

many customers request singleton Camel route in theclustered environmentFabric Master FTW!it is difficult to provide proof of concept for the customerPax Exam + Fabric Master = no brainer demo

Case #3: Fabric Mastercomponent test

public class MasterRoute extends RouteBuilder {

@Override public void configure() throws Exception { from("master:netty-master:netty-http:http://localhost:18081/"). setBody().constant("master"); }

}

the clustered route we want to testonly single Netty instance should handle requests at givenmoment

Case #3: Fabric Mastercomponent test

fabric:create -nfabric:profile-create --parents feature-camel master-nettyfabric:profile-edit --features camel-netty-http master-nettyfabric:profile-edit --bundles mvn:com.example/my-project-bundle/1.0-SNAPSHOT master-netty

Booooring...

Case #3: Fabric Mastercomponent test

Container master = ContainerBuilder.create(). withName("master").withProfiles("master-netty"). assertProvisioningResult().build();

InputStream inputStream = new URL("http://localhost:18081/").openStream();String response = IOUtils.toString(inputStream);assertEquals("master", response);

creating first Netty router container in the clusterfirst router must be the master

Case #3: Fabric Mastercomponent test

Container slave = ContainerBuilder.create(). withName("slave").withProfiles("master-netty"). assertProvisioningResult().build();

no port conflicts? That's good - only the single master node isrunning.

Case #3: Fabric Mastercomponent test

Container master = ...;...master.destroy();

InputStream inputStream = new URL("http://localhost:18081/").openStream();String response = IOUtils.toString(inputStream);assertEquals("master", response);

we are still receiving correct responseslave has been nominated to the master

Exampleshttps://github.com/hekonsek/fuse-pocs/tree/master/fuse-pocs-

fabric

Many thanks!