1
1
package templemore .sbt .cucumber
2
2
3
+ import scala .collection .JavaConverters ._
3
4
import java .lang .reflect .InvocationTargetException
4
5
import java .util .Properties
6
+ import java .io .PrintStream
5
7
6
8
class ReflectingCucumberLauncher (debug : (String ) => Unit , error : (String ) => Unit ) {
7
9
8
10
private val RuntimeOptionsClassName = " cucumber.runtime.RuntimeOptions"
9
11
private val MultiLoaderClassName = " cucumber.runtime.io.MultiLoader"
10
12
private val MultiLoaderClassName_1_0_9 = " cucumber.io.MultiLoader"
11
13
private val RuntimeClassName = " cucumber.runtime.Runtime"
14
+ private val FormatterClassName = " gherkin.formatter.Formatter"
15
+ private val ReporterClassName = " gherkin.formatter.Reporter"
16
+ private val SummaryPrinterClassName = " cucumber.runtime.snippets.SummaryPrinter"
12
17
13
18
def apply (cucumberArguments : Array [String ],
14
19
testClassLoader : ClassLoader ): Int = {
@@ -17,13 +22,12 @@ class ReflectingCucumberLauncher(debug: (String) => Unit, error: (String) => Uni
17
22
runCucumber(runtime).asInstanceOf [Byte ].intValue
18
23
}
19
24
20
- private def runCucumber (runtime : AnyRef ) = try {
21
- val runtimeClass = runtime.getClass
22
- runtimeClass.getMethod(" writeStepdefsJson" ).invoke(runtime)
23
- println(" *** about to call run()..." )
24
- runtimeClass.getMethod(" run" ).invoke(runtime)
25
- println(" *** run() complete, getting exit status..." )
26
- runtimeClass.getMethod(" exitStatus" ).invoke(runtime)
25
+
26
+ private def runCucumber (runtime : CucumberRuntime ) = try {
27
+ runtime.initialise
28
+ runtime.run
29
+ runtime.printSummary
30
+ runtime.exitStatus
27
31
} catch {
28
32
case e : InvocationTargetException => {
29
33
val cause = if ( e.getCause == null ) e else e.getCause
@@ -32,17 +36,54 @@ println("*** run() complete, getting exit status...")
32
36
}
33
37
}
34
38
39
+ case class CucumberRuntime (runtime : AnyRef , options : AnyRef , loader : AnyRef ,
40
+ formatter : AnyRef , reporter : AnyRef , summaryPrinter : AnyRef ,
41
+ classLoader : ClassLoader , formatterClass : Class [_], reporterClass : Class [_]) {
42
+ private val runtimeClass = runtime.getClass
43
+ private val optionsClass = options.getClass
44
+ private val loaderClass = loader.getClass.getInterfaces()(0 )
45
+ private val summaryPrinterClass = summaryPrinter.getClass
46
+
47
+ def initialise = runtimeClass.getMethod(" writeStepdefsJson" ).invoke(runtime)
48
+ def printSummary = summaryPrinterClass.getMethod(" print" , runtimeClass).invoke(summaryPrinter, runtime)
49
+ def exitStatus = runtimeClass.getMethod(" exitStatus" ).invoke(runtime)
50
+
51
+ def run = {
52
+ val featureList = optionsClass.getMethod(" cucumberFeatures" , loaderClass).invoke(options, loader).asInstanceOf [java.util.List [Object ]].asScala
53
+ featureList foreach { feature =>
54
+ val featureClass = feature.getClass
55
+ featureClass.getMethod(" run" , formatterClass, reporterClass, runtimeClass).invoke(feature, formatter, reporter, runtime)
56
+ }
57
+ }
58
+ }
59
+
35
60
private def buildRuntime (properties : Properties ,
36
61
arguments : Array [String ],
37
- classLoader : ClassLoader ): AnyRef = {
62
+ classLoader : ClassLoader ): CucumberRuntime = try {
38
63
def buildLoader (clazz : Class [_]) =
39
64
clazz.getConstructor(classOf [ClassLoader ]).newInstance(classLoader).asInstanceOf [AnyRef ]
40
65
def buildOptions (clazz : Class [_]) =
41
66
clazz.getConstructor(classOf [Properties ], classOf [Array [String ]]).newInstance(properties.asInstanceOf [AnyRef ], arguments).asInstanceOf [AnyRef ]
42
67
43
- val (runtimeClass, optionsClass, loaderClass) = loadCucumberClasses(classLoader)
68
+ val (runtimeClass, optionsClass, loaderClass, formatterClass, reporterClass, summaryPrinterClass) = loadCucumberClasses(classLoader)
69
+
70
+ val options = buildOptions(optionsClass)
71
+ val loader = buildLoader(loaderClass)
72
+
73
+ val formatter = optionsClass.getMethod(" formatter" , classOf [ClassLoader ]).invoke(options, classLoader).asInstanceOf [AnyRef ]
74
+ val reporter = optionsClass.getMethod(" reporter" , classOf [ClassLoader ]).invoke(options, classLoader).asInstanceOf [AnyRef ]
75
+
76
+ val summaryPrinterConstructor = summaryPrinterClass.getConstructor(classOf [PrintStream ])
77
+ val summaryPrinter = summaryPrinterConstructor.newInstance(System .out).asInstanceOf [AnyRef ]
78
+
44
79
val runtimeConstructor = runtimeClass.getConstructor(loaderClass.getInterfaces()(0 ), classOf [ClassLoader ], optionsClass)
45
- runtimeConstructor.newInstance(buildLoader(loaderClass), classLoader, buildOptions(optionsClass)).asInstanceOf [AnyRef ]
80
+ val runtime = runtimeConstructor.newInstance(loader, classLoader, options).asInstanceOf [AnyRef ]
81
+
82
+ CucumberRuntime (runtime, options, loader, formatter, reporter, summaryPrinter, classLoader, formatterClass, reporterClass)
83
+ } catch {
84
+ case e =>
85
+ error(" Unable to construct cucumber runtime. Please report this as an error. (Details: " + e.getMessage + " )" )
86
+ throw e
46
87
}
47
88
48
89
private def loadCucumberClasses (classLoader : ClassLoader ) = try {
@@ -54,10 +95,13 @@ println("*** run() complete, getting exit status...")
54
95
val runtimeOptionsClass = classLoader.loadClass(RuntimeOptionsClassName )
55
96
val multiLoaderClass = classLoader.loadClass(multiLoaderClassName)
56
97
val runtimeClass = classLoader.loadClass(RuntimeClassName )
57
- (runtimeClass, runtimeOptionsClass, multiLoaderClass)
98
+ val formatterClass = classLoader.loadClass(FormatterClassName )
99
+ val reporterClass = classLoader.loadClass(ReporterClassName )
100
+ val summaryPrinterClass = classLoader.loadClass(SummaryPrinterClassName )
101
+ (runtimeClass, runtimeOptionsClass, multiLoaderClass, formatterClass, reporterClass, summaryPrinterClass)
58
102
} catch {
59
103
case e : ClassNotFoundException =>
60
- error(" Unable to load Cucumber classes. Please check your project dependencied . (Details: " + e.getMessage + " )" )
104
+ error(" Unable to load Cucumber classes. Please check your project dependencies . (Details: " + e.getMessage + " )" )
61
105
throw e
62
106
}
63
107
0 commit comments