How can you run GroovyTestCase unit tests inside a Groovy script that is running inside a Java program?
The use here is for running GroovyTestCases inside of SoapUI.
Given:
class ExperimentClassTest extends GroovyTestCase {
void testExperimentClass() {
assertEquals( new ExperimentClass(name: "Hi").name, "Hi" )
}
}
class ExperimentClass {String name}
Then (works):
C:\groovytest>\groovy2.6.0\bin\groovy .\ExperimentClassTest.groovy
.
Time: 0.041
OK (1 test)
But given this (contents of a Groovy script run by SoapUI):
evaluate (new File ('C:/groovytest/ExperimentClassTest.groovy'))
Then (doesn't work):
groovy.lang.MissingMethodException: No signature of method: ExperimentClassTest.main()
Also tried:
new ExperimentClassTest().run()
... which does return a junit.framework.TestResult, but the test hasn't actually run...
new ExperimentClassTest().run().failures().collect {it}
returns
"TestCase.fName cannot be null"
this should work:
new GroovyShell().run( new File('./ExperimentClassTest.groovy'), [] )
actually when you run it as groovy .\ExperimentClassTest.groovy
GroovyShell is called and by class it detects how to run it
https://github.com/groovy/groovy-core/blob/master/src/main/groovy/lang/GroovyShell.java#L295
finally the GroovyShell uses approximately this code to run test case class:
def scriptClass = this.getClass().getClassLoader().parseClass( new File('./ExperimentClassTest.groovy') )
def suite = new junit.framework.TestSuite(scriptClass)
def result = junit.textui.TestRunner.run(suite)
Related
I have a problem with my parameterized tests.
#ParameterizedTest
#ArgumentsSource(CorrectMessagesArgumentProvider.class)
void shouldSendMessageForCorrectConfiguration(SmtpConfiguration configuration) {
var expectedMessageBody = fetchMessage();
var alertSender = new AlertSender(configuration);
var alertSubject = subjectFrom();
alertSender.send(expectedMessageBody, alertSubject);
var receivedMessages = greenMail.getReceivedMessages();
assertEquals(1, receivedMessages.length);
}
#ParameterizedTest
#ArgumentsSource(IncorrectMessagesArgumentProvider.class)
void shouldNotSendMessageForIncorrectConfiguration(SmtpConfiguration smtpConfiguration) {
var expectedMessageBody = fetchMessage();
var alertSender = new AlertSender(smtpConfiguration);
var alertSubject = subjectFrom();
var expectedErrorMessage = "Error sending alert";
var actualErrorMessage =
assertThrows(
SendAlertException.class, () -> alertSender.send(expectedMessageBody, alertSubject));
assertTrue(actualErrorMessage.getMessage().contains(expectedErrorMessage));
}
When I run those tests separetly, they work correctly. But when I run suite, the second test running fails, because it is using arguments from the other test.
They're somehow sharing that resource, but I have no idea how. Any ideas?
Okey, I got it - deep in the class responsible for sending emails, I was creating session object by getDefaultInstance(). It was creating singleton which was available for all JVM processes. When I used getInstance() - it work like a charm.
I am using #NonCPS in my Jenkinsfile function Because I need to get attributes on XML use XmlSlurper and i'm still getting java.io.NotSerializableException error even with the #NonCPS annotation.
Follow is my code
#Field prBranchCoverage
#NonCPS
def xmlCovergeParse(CoverageXml) {
println "start coverage"
def prParser = new XmlSlurper()
prParser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
prParser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
def prCovergeDoc = prParser.parseText(CoverageXml)
def branchCoverage = prCovergeDoc['#line-rate']
return branchCoverages
}
stage('Pr coverage ') {
sh "mvn -V -B -U cobertura:cobertura -PcodehausCoverage -Dmaven.test.failure.ignore=true -DskipWeaving=true test"
publishTestResults cobertura: [archive: true,pattern: "**/target/site/cobertura/coverage.xml"]
def CoverageXml = readFile file: './target/site/cobertura/coverage.xml'
def prBranchCoverage = xmlCovergeParse(CoverageXml)
echo "start coverage"
println prBranchCoverage
}
I get error is:
Error: java.io.NotSerializableException: groovy.util.slurpersupport.Attributes
an exception which occurred:
in field com.cloudbees.groovy.cps.impl.BlockScopeEnv.locals
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv#72e69aed
in field com.cloudbees.groovy.cps.impl.CallEnv.caller
in object com.cloudbees.groovy.cps.impl.FunctionCallEnv#1a22d024
in field com.cloudbees.groovy.cps.Continuable.e
Could anyone help this?
your method xmlCovergeParse(CoverageXml) returns non serializable object
jenkins requires all variables in the pipeline to be Serializable because the next step could be executed on other node then the previous one. so to transfer variables between the nodes they will be serialized.
just add return branchCoverages.toString() in your method xmlCovergeParse
I have a python module, consisting of import_ical.py and __init__.py in my directory . Calling this module from console works, when using:
python -m .import_ical .import_ical.py
When I call the same module using Jython, I get:
TypeError: 'module' object is not callable
at org.python.core.Py.TypeError(Py.java:263)
at org.python.core.PyObject.__call__(PyObject.java:390)
at org.python.core.PyObject.__call__(PyObject.java:496)
at services.imports.CalendarImporter.importFromUrl(CalendarImporter.java:53)
at services.imports.CalendarImporterTest.testMultipleEventsImport(CalendarImporterTest.java:21)
[...]
CalendarImporter.importFromUrl() does the following:
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys");
interpreter.exec("sys.path.append('<dir>')");
interpreter.exec("sys.path.append('/home/<user>/.local/lib/python2.7/site-packages')");
interpreter.exec("import import_ical");
PyObject importIcalPy = interpreter.get("import_ical");
PyObject pythonResult = importIcalPy.__call__(<parameters go here>);
When I execute my JUnit test (CalendarImporterTest) that executes this Jython code, a class file is generated in my module directory, named import_ical$py.class. It contains the following lines (amongst others):
#Filename("<dir>/import_ical.py")
public class import_ical$py extends PyFunctionTable implements PyRunnable {
[....]
static final PyCode __call__$20;
[....]
public PyObject __call__$20(PyFrame var1, ThreadState var2) {
var1.setline(243);
PyObject var3 = var1.getglobal("import_ical").__call__(var2, var1.getlocal(0), var1.getlocal(1), var1.getlocal(2));
var1.f_lasti = -1;
return var3;
}
}
Debugging to the last line of my CalendarImporter Java code shown above gives me the following variables states:
interpreter = {PythonInterpreter}
[...]
globals = {PyStringMap}
table
[...]
1 = {ConcurrentHashMap$MapEntry} "import_ical" -> "<module 'import_ical' from '<dir>/import_ical$py.class'>"
[...]
[...]
[...]
importIcalPy = {PyModule}
[...]
__dict__ = {PyStringMap}
table
[...]
19 = {ConcurrentHashMap$MapEntry} "import_ical" -> "<function import_ical at 0xc>"
[...]
32 = {ConcurrentHashMap$MapEntry} "__call__" -> "<function __call__ at 0x13>"
[...]
[...]
[...]
As a python newbie, I cannot detect anything that would arouse my scepticism with regards to the generated class file of the module and even the variables' state shown above seems to tell me that there is a proper function __call__ within in my python module importIcalPy.
Note: I had already added the function __call__ to my python module to make the module by "callable" from Jython and catch this error - obviously without success.
So can anyone please tell me: why do I get that "not callable" error? And what can I do to prevent it? Any help is greatly appreciated - thank you!
[Comment: I have intensely searched for a solution both, in Stackoverflow and using a big search engine, but all search results lead me to another problem where a python module could not call another python module.]
Finally, and thanks to the hints of user2357112, I've found a fix. Replace the content of CalendarImporter.importFromUrl() shown above with the following code:
PythonInterpreter.initialize(System.getProperties(), System.getProperties(), new String[0]);
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys");
interpreter.exec("sys.path.append('<dir>')");
interpreter.exec("sys.path.append('/home/<user>/.local/lib/python2.7/site-packages')");
interpreter.exec("import import_ical");
// set variables if necessary in script:
// interpreter.set("__file__", <myFile>);
// set system argument variables (one append per variable):
interpreter.exec("sys.argv.append('".concat("<myVar>").concat("')"));
interpreter.execfile("<fileWithQualifiedPath>");
PyObject importIcalPy = interpreter.get("import_ical");
PyObject pythonResult = importIcalPy.__call__(new PyString("<myScriptArgument>"));
Hope, it will help someone.
i have the following Java-Code that i want to convert to groovy:
String containerId = "545cdc81a969";
ExecCreateCmdResponse execCreateCmdResponse = dockerClient
.execCreateCmd(containerId)
.withAttachStdout(true)
.withCmd("sh", "-c", "sleep 5 && exit 5")
.exec();
ExecStartResultCallback execStartCmd =
dockerClient.execStartCmd(execCreateCmdResponse.getId())
.exec(new ExecStartResultCallback(System.out, System.err))
.awaitCompletion();
My current version in groovy is this:
String id = "545cdc81a969";
def execCreateCmdResponse = dockerClient
.execCreateCmd(id)
.withAttachStdout(true)
.withCmd('sh','-c','sleep 5 && exit 5')
.exec()
dockerClient.execStartCmd(execCreateCmdResponse.getId())
.withDetach(false)
.exec(new ExecStartResultCallback(System.out, System.err))
.awaitCompletion()
My problem is, that i get the following error, when i try to run the groovy code:
* What went wrong:
Execution failed for task ':werner'.
> No signature of method: com.github.dockerjava.core.command.ExecStartCmdImpl.exec() is applicable for argument types: (com.github.dockerjava.core.command.ExecStartResultCallback) values: [com.github.dockerjava.core.command.ExecStartResultCallback#6ce82155]
Possible solutions: exec(com.github.dockerjava.api.async.ResultCallback), exec(com.github.dockerjava.api.async.ResultCallback), every(), grep(), every(groovy.lang.Closure), grep(java.lang.Object)
The Java-exec-Method has the signature:
public <T extends ResultCallback<Frame>> T exec(T resultCallback);
I tried to cast "new ExecStartResultCallback(System.out, System.err)" to "ResultCallback", but it did not work.
Is there any way to force Groovy to handle the instance as a ResultCallback-Instance so that the correct method is called?
Regards,
marbon
A colleague helped with this problem and we found out, that the instance dockerClient used a custom classloader, which my has some problems. It could be solved by instantiating the new ExecStartResultCallback(System.out, System.err) with the same classloader from dockerInstance:
ClassLoader dockerClientClassLoader = dockerClient.getClass().getClassLoader()
Class callbackClass = dockerClientClassLoader.loadClass("com.github.dockerjava.core.command.ExecStartResultCallback")
def callback = callbackClass.getDeclaredConstructor(OutputStream.class, OutputStream.class).newInstance(System.out, System.err);
dockerClient.execStartCmd(execCreateCmdResponse.getId())
.withDetach(false)
.exec(callback)
.awaitCompletion()
I am using Weka to create a classifier via the Java API.
The instances are created using java code.
The classifier is being created from code as well via passing following
String args[]=" -x 10 -s 1 -W weka.classifiers.functions.Logistic".split(" ");
String classname;
String[] tmpOptions = Utils.splitOptions(Utils.getOption("W", args));
classname = tmpOptions[0];
System.out.println(classname);
Classifier cls = (Classifier) Utils.forName(Classifier.class, classname, tmpOptions);
It works fine and does cross validation.
After that I once again load my training instances and label their output as ?
and pass it to classifier using
for (int index = 0; index < postDatas.size(); index++) {
Instance instance = nominal.instance(index);
double label = classifier.classifyInstance(instance);
System.out.println(label);
}
classifier.classifyInstance(instance); gives me following exception:
java.lang.NullPointerException
at weka.classifiers.functions.Logistic.distributionForInstance(Logistic.java:710)
any clues to where am I going wrong?
Since you didn't provide all relevant information, I'll take a shot in the dark:
I'm assuming that you're using Weka version 3.7.5 and I found the following source code for Logistic.java online
public double [] distributionForInstance(Instance instance) throws Exception {
// line 710
m_ReplaceMissingValues.input(instance);
instance = m_ReplaceMissingValues.output();
...
}
Assuming you didn't pass null for instance, this only leaves m_ReplaceMissingValues. That member is initialized when the method Logistic.buildClassifier(Instances train)is called:
public void buildClassifier(Instances train) throws Exception {
...
// missing values
m_ReplaceMissingValues = new ReplaceMissingValues();
m_ReplaceMissingValues.setInputFormat(train);
train = Filter.useFilter(train, m_ReplaceMissingValues);
...
}
It looks like you've never trained your classifier Logistic on any data after you created the object in the line
Classifier cls = (Classifier) Utils.forName(Classifier.class, classname, tmpOptions);