[testng] 17/355: Add 'parent-module' property to suite

Eugene Zhukov eugene-guest at moszumanska.debian.org
Tue Aug 18 10:19:42 UTC 2015


This is an automated email from the git hooks/post-receive script.

eugene-guest pushed a commit to annotated tag OpenBSD
in repository testng.

commit 21c6d08b4857e3c9d3d2d21934f35cf787e013a5
Author: Dariusz Luksza <dariusz at luksza.org>
Date:   Fri Aug 2 11:52:36 2013 +0200

    Add 'parent-module' property to suite
    
    With 'parent-module' property for suite users can declare parent Guice
    module for all modules and module factories used in suite. This approach
    enables tons of possibilities and possible use cases.
    
    When 'parent-module' property is set, TestNG will create all Guice
    modules and module factories using getInstance method from injector
    created with 'parent-module'. This enables dependency injection in
    modules and module factories. Also injectors for tests will be created
    as child injectors, this way all common binding can be declared in
    parent module.
---
 doc/documentation-main.html                        |  9 +++
 src/main/java/org/testng/ISuite.java               | 14 ++++-
 src/main/java/org/testng/SuiteRunner.java          | 14 +++++
 src/main/java/org/testng/internal/ClassImpl.java   | 66 +++++++++++++---------
 .../java/org/testng/remote/SuiteDispatcher.java    |  1 +
 .../java/org/testng/xml/TestNGContentHandler.java  |  4 ++
 src/main/java/org/testng/xml/XmlSuite.java         | 15 +++++
 src/main/resources/testng-1.0.dtd                  |  1 +
 8 files changed, 95 insertions(+), 29 deletions(-)

diff --git a/doc/documentation-main.html b/doc/documentation-main.html
index 0a8bd32..2e4ab10 100644
--- a/doc/documentation-main.html
+++ b/doc/documentation-main.html
@@ -2226,7 +2226,16 @@ public interface IModuleFactory {
 
 Your factory will be passed an instance of the test context and the test class that TestNG needs to instantiate. Your <tt>createModule</tt> method should return a Guice Module that will know how to instantiate this test class. You can use the test context to find out more information about your environment, such as parameters specified in <tt>testng.xml</tt>, etc...
 
+You will get even more flexibility and Guice power with parent-module siute parameter. Here is how you can define parent-module in your test.xml file:
 
+<pre class="brush: xml">
+<suite parent-module="com.example.SuiteParenModule">
+</suite>
+</pre>
+
+TestNG will create this module only once for given suite. Will also use this module for obtaining instances of test specific Guice modules and module factories, then will create child injector for each test class.
+
+With such approach you can declare all common bindings in parent-module also you can inject binding declared in parent-module in module and module factory.
 
 <!-------------------------------------
   INVOKED METHOD LISTENERS
diff --git a/src/main/java/org/testng/ISuite.java b/src/main/java/org/testng/ISuite.java
index e24587f..3ab5ed0 100755
--- a/src/main/java/org/testng/ISuite.java
+++ b/src/main/java/org/testng/ISuite.java
@@ -1,13 +1,15 @@
 package org.testng;
 
 
-import org.testng.internal.annotations.IAnnotationFinder;
-import org.testng.xml.XmlSuite;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import org.testng.internal.annotations.IAnnotationFinder;
+import org.testng.xml.XmlSuite;
+
+import com.google.inject.Injector;
+
 /**
  * Interface defining a Test Suite.
  *
@@ -42,6 +44,8 @@ public interface ISuite extends IAttributes {
    */
   public String getParallel();
 
+  public String getParentModule();
+
   /**
    * @return The value of this parameter, or null if none was specified.
    */
@@ -103,6 +107,10 @@ public interface ISuite extends IAttributes {
 
   public void addListener(ITestNGListener listener);
 
+  public Injector getParentInjector();
+
+  public void setParentInjector(Injector injector);
+
   /**
    * @return the total number of methods found in this suite. The presence of
    * factories or data providers might cause the actual number of test methods
diff --git a/src/main/java/org/testng/SuiteRunner.java b/src/main/java/org/testng/SuiteRunner.java
index 5919893..d1fa95c 100644
--- a/src/main/java/org/testng/SuiteRunner.java
+++ b/src/main/java/org/testng/SuiteRunner.java
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import com.google.inject.Injector;
 
 /**
  * <CODE>SuiteRunner</CODE> is responsible for running all the tests included in one
@@ -48,6 +49,7 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener
 
   private String m_outputDir; // DEFAULT_OUTPUT_DIR;
   private XmlSuite m_suite;
+  private Injector m_parentInjector;
 
   transient private List<ITestListener> m_testListeners = Lists.newArrayList();
   transient private ITestRunnerFactory m_tmpRunnerFactory;
@@ -233,6 +235,18 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener
     return m_suite.getParallel();
   }
 
+  public String getParentModule() {
+    return m_suite.getParentModule();
+  }
+
+  public Injector getParentInjector() {
+    return m_parentInjector;
+  }
+
+  public void setParentInjector(Injector injector) {
+    m_parentInjector = injector;
+  }
+
   @Override
   public void run() {
     invokeListeners(true /* start */);
diff --git a/src/main/java/org/testng/internal/ClassImpl.java b/src/main/java/org/testng/internal/ClassImpl.java
index 2f6eabe..a687dce 100755
--- a/src/main/java/org/testng/internal/ClassImpl.java
+++ b/src/main/java/org/testng/internal/ClassImpl.java
@@ -1,10 +1,13 @@
 package org.testng.internal;
 
+import static org.testng.internal.Utils.isStringNotEmpty;
+
 import com.google.inject.Injector;
 import com.google.inject.Module;
 
 import org.testng.IClass;
 import org.testng.IModuleFactory;
+import org.testng.ISuite;
 import org.testng.ITest;
 import org.testng.ITestContext;
 import org.testng.ITestObjectFactory;
@@ -41,6 +44,7 @@ public class ClassImpl implements IClass {
   private String m_testName = null;
   private XmlClass m_xmlClass;
   private ITestContext m_testContext;
+  private final boolean m_hasParentModule;
 
   public ClassImpl(ITestContext context, Class cls, XmlClass xmlClass, Object instance,
       Map<Class, IClass> classes, XmlTest xmlTest, IAnnotationFinder annotationFinder,
@@ -56,6 +60,7 @@ public class ClassImpl implements IClass {
     if (instance instanceof ITest) {
       m_testName = ((ITest) instance).getTestName();
     }
+    m_hasParentModule = isStringNotEmpty(m_testContext.getSuite().getParentModule());
   }
 
   private static void ppp(String s) {
@@ -124,49 +129,58 @@ public class ClassImpl implements IClass {
   private Object getInstanceFromGuice() {
     Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, m_class);
     if (annotation == null) return null;
+    Injector parentInjector = getParentInjector();
 
     Guice guice = (Guice) annotation;
-    List<Module> moduleInstances = Lists.newArrayList(getModules(guice, m_class));
+    List<Module> moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, m_class));
 
     // Reuse the previous injector, if any
     Injector injector = m_testContext.getInjector(moduleInstances);
     if (injector == null) {
-      injector = com.google.inject.Guice.createInjector(moduleInstances);
+      injector = parentInjector.createChildInjector(moduleInstances);
       m_testContext.addInjector(moduleInstances, injector);
     }
     return injector.getInstance(m_class);
   }
 
-  private Module[] getModules(Guice guice, Class<?> testClass) {
+  public Injector getParentInjector() {
+    ISuite suite = m_testContext.getSuite();
+    // Reuse the previous parent injector, if any
+    Injector injector = suite.getParentInjector();
+    if (injector == null) {
+      if (m_hasParentModule) {
+        Class<?> parentModule = ClassHelper.forName(suite.getParentModule());
+        if (parentModule == null) {
+          throw new TestNGException("Cannot load parent Guice module class: " + parentModule);
+        }
+        Module module = (Module) ClassHelper.newInstance(parentModule);
+        injector = com.google.inject.Guice.createInjector(module);
+      } else {
+        injector = com.google.inject.Guice.createInjector();
+      }
+      suite.setParentInjector(injector);
+    }
+    return injector;
+  }
+
+  private Module[] getModules(Guice guice, Injector parentInejctor, Class<?> testClass) {
     List<Module> result = Lists.newArrayList();
     for (Class<? extends Module> moduleClass : guice.modules()) {
-      try {
-        List<Module> modules = m_testContext.getGuiceModules(moduleClass);
-        if (modules != null && modules.size() > 0) {
-          result.addAll(modules);
-        } else {
-          Module instance = moduleClass.newInstance();
-          result.add(instance);
-          m_testContext.addGuiceModule(moduleClass, instance);
-        }
-      } catch (InstantiationException e) {
-        throw new TestNGException(e);
-      } catch (IllegalAccessException e) {
-        throw new TestNGException(e);
+      List<Module> modules = m_testContext.getGuiceModules(moduleClass);
+      if (modules != null && modules.size() > 0) {
+        result.addAll(modules);
+      } else {
+        Module instance = parentInejctor.getInstance(moduleClass);
+        result.add(instance);
+        m_testContext.addGuiceModule(moduleClass, instance);
       }
     }
     Class<? extends IModuleFactory> factory = guice.moduleFactory();
     if (factory != IModuleFactory.class) {
-      try {
-        IModuleFactory factoryInstance = factory.newInstance();
-        Module moduleClass = factoryInstance.createModule(m_testContext, testClass);
-        if (moduleClass != null) {
-          result.add(moduleClass);
-        }
-      } catch (InstantiationException e) {
-        throw new TestNGException(e);
-      } catch (IllegalAccessException e) {
-        throw new TestNGException(e);
+      IModuleFactory factoryInstance = parentInejctor.getInstance(factory);
+      Module moduleClass = factoryInstance.createModule(m_testContext, testClass);
+      if (moduleClass != null) {
+        result.add(moduleClass);
       }
     }
 
diff --git a/src/main/java/org/testng/remote/SuiteDispatcher.java b/src/main/java/org/testng/remote/SuiteDispatcher.java
index c5e9635..f37bafa 100644
--- a/src/main/java/org/testng/remote/SuiteDispatcher.java
+++ b/src/main/java/org/testng/remote/SuiteDispatcher.java
@@ -114,6 +114,7 @@ public class SuiteDispatcher
             tmpSuite.setSkipFailedInvocationCounts(suite.skipFailedInvocationCounts());
 						tmpSuite.setName("Temporary suite for " + test.getName());
 						tmpSuite.setParallel(suite.getParallel());
+						tmpSuite.setParentModule(suite.getParentModule());
 						tmpSuite.setParameters(suite.getParameters());
 						tmpSuite.setThreadCount(suite.getThreadCount());
             tmpSuite.setDataProviderThreadCount(suite.getDataProviderThreadCount());
diff --git a/src/main/java/org/testng/xml/TestNGContentHandler.java b/src/main/java/org/testng/xml/TestNGContentHandler.java
index 5a7d113..af2e338 100755
--- a/src/main/java/org/testng/xml/TestNGContentHandler.java
+++ b/src/main/java/org/testng/xml/TestNGContentHandler.java
@@ -163,6 +163,10 @@ public class TestNGContentHandler extends DefaultHandler {
           Utils.log("Parser", 1, "[WARN] Unknown value of attribute 'parallel' at suite level: '" + parallel + "'.");
         }
       }
+      String parentModule = attributes.getValue("parent-module");
+      if (parentModule != null) {
+        m_currentSuite.setParentModule(parentModule);
+      }
       String configFailurePolicy = attributes.getValue("configfailurepolicy");
       if (null != configFailurePolicy) {
         if (XmlSuite.SKIP.equals(configFailurePolicy) || XmlSuite.CONTINUE.equals(configFailurePolicy)) {
diff --git a/src/main/java/org/testng/xml/XmlSuite.java b/src/main/java/org/testng/xml/XmlSuite.java
index c0aa2de..61612eb 100755
--- a/src/main/java/org/testng/xml/XmlSuite.java
+++ b/src/main/java/org/testng/xml/XmlSuite.java
@@ -62,6 +62,8 @@ public class XmlSuite implements Serializable, Cloneable {
   public static String DEFAULT_PARALLEL = "false";
   private String m_parallel = DEFAULT_PARALLEL;
 
+  private String m_parentModule = "";
+
   /** Whether to SKIP or CONTINUE to re-attempt failed configuration methods. */
   public static String DEFAULT_CONFIG_FAILURE_POLICY = SKIP;
   private String m_configFailurePolicy = DEFAULT_CONFIG_FAILURE_POLICY;
@@ -156,6 +158,11 @@ public class XmlSuite implements Serializable, Cloneable {
     return m_parallel;
   }
 
+
+  public String getParentModule() {
+    return m_parentModule;
+  }
+
   public ITestObjectFactory getObjectFactory() {
     return m_objectFactory;
   }
@@ -172,6 +179,10 @@ public class XmlSuite implements Serializable, Cloneable {
     m_parallel = parallel;
   }
 
+  public void setParentModule(String parentModule) {
+    m_parentModule = parentModule;
+  }
+
   /**
    * Sets the configuration failure policy.
    * @param configFailurePolicy the config failure policy
@@ -442,6 +453,9 @@ public class XmlSuite implements Serializable, Cloneable {
     if(null != m_objectFactory) {
       p.setProperty("object-factory", m_objectFactory.getClass().getName());
     }
+    if (isStringNotEmpty(m_parentModule)) {
+      p.setProperty("parent-module", getParentModule());
+    }
     XmlUtils.setProperty(p, "allow-return-values", String.valueOf(getAllowReturnValues()),
         DEFAULT_ALLOW_RETURN_VALUES.toString());
     xsb.push("suite", p);
@@ -570,6 +584,7 @@ public class XmlSuite implements Serializable, Cloneable {
     result.setName(getName());
     result.setListeners(getListeners());
     result.setParallel(getParallel());
+    result.setParentModule(getParentModule());
     result.setConfigFailurePolicy(getConfigFailurePolicy());
     result.setThreadCount(getThreadCount());
     result.setDataProviderThreadCount(getDataProviderThreadCount());
diff --git a/src/main/resources/testng-1.0.dtd b/src/main/resources/testng-1.0.dtd
index ff85283..f6920a3 100755
--- a/src/main/resources/testng-1.0.dtd
+++ b/src/main/resources/testng-1.0.dtd
@@ -61,6 +61,7 @@ Cedric Beust & Alexandru Popescu
     junit (true | false) "false"
     verbose CDATA #IMPLIED
     parallel (false | methods | tests | classes | instances) "false"
+    parent-module CDATA #IMPLIED
     configfailurepolicy (skip | continue) "skip"
     thread-count CDATA "5"
     annotations CDATA #IMPLIED

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/testng.git



More information about the pkg-java-commits mailing list