3. AgendaAgenda
•• Introduction: What Testing Is NotIntroduction: What Testing Is Not
•• OSGi Test Harness OverviewOSGi Test Harness Overview
•• OSGi Test Framework andOSGi Test Framework and JUnitJUnit
•• User Oriented xUser Oriented x OSGiOSGi Service OrientedService Oriented
•• Guidelines for Writing OSGi Test CasesGuidelines for Writing OSGi Test Cases
•• OSGiOSGi Testing PatternsTesting Patterns
4. Introduction: What Testing Is NotIntroduction: What Testing Is Not
•• Demonstrating the Lack of BugsDemonstrating the Lack of Bugs
–– ““it is impossible to specify any algorithm which, given anit is impossible to specify any algorithm which, given an
arbitrary input (computer program), can decide whether or notarbitrary input (computer program), can decide whether or not
the system will eventually haltthe system will eventually halt””, (Allan Turing), (Allan Turing)
•• DebuggingDebugging
–– This is a pair programming and peer reviewing activityThis is a pair programming and peer reviewing activity
•• Quality Assurance JobQuality Assurance Job
–– It is also the engineer responsibilityIt is also the engineer responsibility
•• The Final Hurdle to Release the CodeThe Final Hurdle to Release the Code
–– Testing must be treated as a continuous activityTesting must be treated as a continuous activity
–– E.g.: OSGi Compliance ProgramE.g.: OSGi Compliance Program
5. •• OSGi Test Director BundleOSGi Test Director Bundle
–– Manage test suites; register targets; set testing propertiesManage test suites; register targets; set testing properties
–– Provides a HTTP serverProvides a HTTP server
•• Target test bundleTarget test bundle
–– RunsRuns on theon the device under testdevice under test
–– ControlledControlled by the directorby the director
–– InstallInstall the Test bundles (tbcN.jar) /the Test bundles (tbcN.jar) / runrun the tests /the tests / postpost the resultsthe results
PC / Workstation
OSGi
Test
Director
Test
JARs.
OSGi Device
CVM
FP/PP
OSGi + MEG/VEG
Target Bundle
“P2P Protocol”
OSGi Test Harness OverviewOSGi Test Harness Overview
a1
7. OSGi Test Framework and JUnitOSGi Test Framework and JUnit
•• Does OSGi Test Framework use JUnit?Does OSGi Test Framework use JUnit?
–– Yes and NoYes and No
–– It can do much more than evaluate the execution of a singleIt can do much more than evaluate the execution of a single
classclass
•• In Common:In Common:
–– Assertion PatternsAssertion Patterns
–– Both can be run inside EclipseBoth can be run inside Eclipse
•• OSGi:OSGi:
–– Test Control has AllPermissions over the FrameworkTest Control has AllPermissions over the Framework
–– Test Control has access to the BundleContextTest Control has access to the BundleContext
–– Test Case itself is an OSGi BundleTest Case itself is an OSGi Bundle
–– Service drivenService driven
•• JUnit:JUnit:
–– Class drivenClass driven
8. User Oriented x OSGi Service Oriented TestingUser Oriented x OSGi Service Oriented Testing
User Oriented:User Oriented:
1.1. Bases tests onBases tests on
requirementsrequirements
2.2. Tested API is neverTested API is never
changedchanged
3.3. Business process isBusiness process is
usually an entityusually an entity
4.4. AssumesAssumes
Components will beComponents will be
always presentalways present
OSGi Service Oriented:OSGi Service Oriented:
1.1. Bases tests onBases tests on
services contractsservices contracts
2.2. Normally extendsNormally extends
service interfaces forservice interfaces for
testingtesting
3.3. Business process is aBusiness process is a
set of servicesset of services
4.4. Assumes ComponentsAssumes Components
have a dynamichave a dynamic
availabilityavailability
9. Writing OSGi Test Cases GuidelinesWriting OSGi Test Cases Guidelines
•• RobustnessRobustness
–– Perform automatic testing when possiblePerform automatic testing when possible
–– Sharing static variables is not badSharing static variables is not bad
–– Avoid Checked Exception handlingAvoid Checked Exception handling
•• PerformancePerformance
–– Do care about cleaning up a Test CaseDo care about cleaning up a Test Case
state, before execution of another teststate, before execution of another test
casecase
10. Writing OSGi Test Cases GuidelinesWriting OSGi Test Cases Guidelines
•• CodingCoding
–– Test the interfaces and not the implementationTest the interfaces and not the implementation
–– Write as many assertions per test cases asWrite as many assertions per test cases as
necessarynecessary
–– Do care about the test suite jar sizeDo care about the test suite jar size
•• Ease of UseEase of Use
–– Do not bother waiting forever for asynchronousDo not bother waiting forever for asynchronous
events, yet another definition for don't handleevents, yet another definition for don't handle
specificspecific TIMEOUTTIMEOUT
11. OSGi Test PatternsOSGi Test Patterns
•• Unit Test PatternUnit Test Pattern
–– Test Framework automatically finds and invokesTest Framework automatically finds and invokes TestControlTestControl
methodsmethods
–– In each test method of test control, call Test ClassesIn each test method of test control, call Test Classes’’ runrun
methodmethod
–– Remember doing Cleanup after test case executionRemember doing Cleanup after test case execution
12. OSGi Test PatternsOSGi Test Patterns
•• Unit Test ImplementationUnit Test Implementation
public classpublic class TestControlTestControl extendsextends
DefaultTestBundleControlDefaultTestBundleControl {{
public voidpublic void
testtestClassUnderTestMethodAClassUnderTestMethodA() {() {
newnew
TestMethodA(this).runTestMethodA(this).run();();
}}
public classpublic class TestMethodATestMethodA {{
privateprivate TestControlTestControl tbctbc;;
publicpublic TestMethodA(TestControlTestMethodA(TestControl tbctbc) {) {
this.tbcthis.tbc == tbctbc;;
}}
public void run() {public void run() {
testMethodA001();testMethodA001();
}}
private void testMethodA001() {private void testMethodA001() {
StringString paramparam = "test";= "test";
try {try {
ClassUnderTestClassUnderTest cut = newcut = new
ClassUnderTest(ClassUnderTest(paramparam););
tbc.assertEquals("Paramtbc.assertEquals("Param was correctlywas correctly
set",set", paramparam,, cut.getParamcut.getParam());());
} catch (Exception e) {} catch (Exception e) {
tbc.fail("Unexpectedtbc.fail("Unexpected Exception"+Exception"+
e.getClass().getNamee.getClass().getName());());
}}
}}
}}
13. OSGi Test PatternsOSGi Test Patterns
•• Bundles Test PatternBundles Test Pattern
•• In the Test Control prepare method:In the Test Control prepare method:
–– Install TB1 bundleInstall TB1 bundle
–– Set bundle PermissionsSet bundle Permissions
–– Get registeredGet registered TestFactoryTestFactory
14. OSGi Test PatternsOSGi Test Patterns
•• Bundles Test ImplementationBundles Test Implementation
public classpublic class TestControlTestControl extendsextends
DefaultTestBundleControlDefaultTestBundleControl {{
privateprivate TestFactoryTestFactory tftf;;
public void prepare() {public void prepare() {
Bundle b = null;Bundle b = null;
try {try {
b =b = installBundle("tb1.jar")installBundle("tb1.jar");;
tftf = (= (TestFactoryTestFactory))
getService(TestFactory.classgetService(TestFactory.class));;
} catch (Exception e) {} catch (Exception e) {
log("Failedlog("Failed to prepare the test");to prepare the test");
}}
setBundlePermission(b.getLocationsetBundlePermission(b.getLocation());());
}}
public voidpublic void
testBundleUnderTestPrivilegedActionAtestBundleUnderTestPrivilegedActionA() {() {
TestServiceTestService[][] tsts ==
tf.getInstances(thistf.getInstances(this););
ts[0].run();ts[0].run();
}}
public class TB1Activator implementspublic class TB1Activator implements
BundleActivatorBundleActivator,, TestFactoryTestFactory {{
privateprivate ServiceRegistrationServiceRegistration srsr;;
public voidpublic void start(BundleContextstart(BundleContext bcbc))
throws Exception {throws Exception {
srsr ==
bc.registerService(TestFactory.class.getNabc.registerService(TestFactory.class.getNa
meme(), this, null);(), this, null);
}}
public voidpublic void stop(BundleContextstop(BundleContext context)context)
throws Exception {throws Exception {
sr.unregistersr.unregister();();
}}
publicpublic TestServiceTestService[][]
getInstances(DefaultTestBundleControlgetInstances(DefaultTestBundleControl tbctbc))
{{
return newreturn new TestServiceTestService[] {[] {
newnew
TestPrivilegedActionA((TestControlTestPrivilegedActionA((TestControl)) tbctbc))
};};
}}
15. OSGi Test PatternsOSGi Test Patterns
•• Service Contracts Pattern:Service Contracts Pattern:
–– Register as ServiceInterface instanceRegister as ServiceInterface instance
–– Get Service as ServiceInterfaceTest instanceGet Service as ServiceInterfaceTest instance
16. OSGi Test PatternsOSGi Test Patterns
•• Service Contracts ImplementationService Contracts Implementation
public classpublic class TestControlTestControl extendsextends DefaultTestBundleControlDefaultTestBundleControl {{
public void prepare() {public void prepare() {
ServiceInterfaceTestServiceInterfaceTest sit = newsit = new ServiceInterfaceTestImplServiceInterfaceTestImpl();();
getContext().registerService(getContext().registerService(ServiceInterface.class.getNameServiceInterface.class.getName()(), sit, null);, sit, null);
}}
public voidpublic void testServiceContracttestServiceContract() {() {
newnew TestServiceContract(this).runTestServiceContract(this).run();();
}}
public classpublic class TestServiceContractTestServiceContract {{
public void run() {public void run() {
testServiceContract001();testServiceContract001();
}}
public void testServiceContract001() {public void testServiceContract001() {
//action that calls//action that calls doSomeThingdoSomeThing inin ServiceInterfaceServiceInterface
ImplementationImplementation
ServiceInterfaceTestServiceInterfaceTest sit = null;sit = null;
try {try {
sit = (sit = (ServiceInterfaceTestServiceInterfaceTest)) tbc.getServicetbc.getService
((ServiceInterface.classServiceInterface.class););
String[] values =String[] values = sit.getValuessit.getValues();();
tbc.assertEquals("doSomethingtbc.assertEquals("doSomething method called",method called",
"true", values[0]);"true", values[0]);
} catch (Exception e) {} catch (Exception e) {
tbc.fail("Unexpectedtbc.fail("Unexpected
Exception"+e.getClass().getNameException"+e.getClass().getName());());
}}
public classpublic class ServiceInterfaceTestImplServiceInterfaceTestImpl implementsimplements
ServiceInterfaceTestServiceInterfaceTest {{
private Stringprivate String someThingCalledsomeThingCalled;;
public String[]public String[] getValuesgetValues() {() {
return newreturn new String[]{someThingCalledString[]{someThingCalled};};
}}
public void reset() {public void reset() {
someThingCalledsomeThingCalled = "false";= "false";
}}
public voidpublic void doSomeThingdoSomeThing()() {{
someThingCalledsomeThingCalled = "true";= "true";
}}
}}
17. ConclusionsConclusions
•• Compliance programs will neverCompliance programs will never
mathematically cover 100% of themathematically cover 100% of the
specificationsspecifications
•• Robustness, Performance and Ease of UseRobustness, Performance and Ease of Use
are not main requirements of test casesare not main requirements of test cases
•• OSGiOSGi Test Framework can be extended for:Test Framework can be extended for:
–– Unit testingUnit testing
–– Bundle privileged actions testingBundle privileged actions testing
–– For services contracts testingFor services contracts testing