jython2.2.1 AttributeError: 'javainstance' object has no attribute '__call__' - groovy

I'm having trouble trying to run jython code embedded in a compiled groovy application. The same jython code works fine when it is embedded in a java application (The Grinder 3.1)
In the groovy code I use the org.python.util.PythonInterpreter class (from jython 2.2.1) to create a callable instance of a class called TestRunner (this is a requirement from The Grinder).
Illustrative jython code example:
class TestRunner:
def __init__(self):
doinitstuff()
def __call__():
a = A()
a.work()
class A:
def __init__(self):
self.b = B()
def work(self):
print "Calling methodcall"
self.b.methodcall()
class B:
def __init__(self):
self.webservice = WebServiceStubImplementedInJava()
print str(self.webservice)
def methodcall(self):
print "In methodcall"
try:
return self.webservice.soapmethod()
except:
log_error()
raise
Here is the output when I run the above code:
The TestRunners __call__() method will invoke the work() method of a class A instance, and the webservice stub's toString output is printed.
The "Calling methodcall" message is printed.
The "In methodcall" message is never printed, and instead I get: AttributeError: 'javainstance' object has no attribute '__call__'. The stacktrace ends with self.b.methodcall()
Do you have any idea why the invocation of self.b.methodcall() should result in AttributeError: 'javainstance' object has no attribute __call__
Adding some context to the problem...
I'm trying to use a Groovy class to execute the work that a Grinder worker thread would perform when we performance test our product.
I use groovy just for the sake of "less verbose code", but might have to switch over to plain old java if it's groovy that causes the problem.
The reason for doing this is that I need to find out which files are actually used by Grinder for a given test scenario.
We have hundreds of *.py files and configuration files etc, but only a subset of them are used for one specific test scenario. All of them are used in some test scenario.
This makes it quite hard for a "beginner" to understand how to configure a test so I'm trying to build a "test configurator wizard" that set up a test scenario without forcing the user/tester to edit all config files manually.
This wizard will collect the relevant files from a "repository" and put them in a folder where the "Grinder Console" can present them to the user.
So, the way I use to find out which files are used by Grinder is to use AOP (AspectJ) to capture all calls to java.io.FileInputStream(java.io.File) from any code in the org.python.util and org.python.core packages.
The "advice" I apply to these join-points is to print the file name to System.out.
I use load-time weaving for this, so I can run the groovy/java/jython code with our without
AOP enabled. The AttributeErrorproblem occurs regardless if I have AOP enabled or not.
I have a vague suspicion that the AttributeError problem could be caused by some classloader mismatch when a "groovy" class executes the PythonInterpreter methods, but I'm far from sure about this.
I'm not sure if groovy is doing any kind of runtime bytecode editing when it loads classes and if that confuses the PythonInterpreter.
The groovy code itself is precompiled so I use the regular java.exe to launch the process.

Related

Why is doctest skipping tests on imported methods?

I have a python module some_module with an __init__.py file that imports methods, like this:
from .some_python_file import some_method
some_method has a docstring that includes doctests:
def some_method():
"""
>>> assert False
"""
But when I run doctest on the module, it passes even if the tests should fail.
import some_module
# How do I get this to consistently fail, regardless of whether
# `some_module.some_method` was declared inline or imported?
assert doctest.testmod(some_module).failed == 0
If I instead define some_method within the __init__.py file, the doctest correctly fails.
Why are these two situations behaving differently? The method is present and has the same __doc__ attribute in both cases.
How do I get doctest to run the tests defined in the dostrings of methods that were imported into the module?
In Python a module is define by a single file and in your case some_python_file is a module while __init__ is another one. Doctest has a check to run tests only for examples reachable from the module which can be found here.
The best way to see this behaviour in practice is to use PDB and pdb.set_trace() right before you call doctest.testmod(some_module) and step inside to follow the logic.
LE:
Doctest ignores imported methods per this comment. If you want to be able to run your test you should probably define a main function in your module and run the test test with python some_module.py. You can follow this example.
To achieve your expected behaviour you need to manually create a __test__ dict in your init file:
from .some_python_file import some_method
__test__ = {"some_method": some_method}
See this link as well.
Objects imported into the module are not searched.
See docs on which docstrings are examined.
You can can inject the imported function into the module's __test__ attribute to have imported objects tested:
__test__ = {'some_method': some_method}
I stumbled upon this question because I was hacking a __doc__ attribute of an imported object.
from foo import bar
bar.__doc__ = """
>>> assert True
"""
and I was also wondering why the doctest of bar did not get executed by the doctest runner.
The previously given answer to add a `__test__` mapping solved it for good.
```python
__test__ = dict(bar=bar.__doc__)
I think the explanation for this behaviour is the following. If you are using a library, lets say NumPy, you do not want all of their doctests to be collected and run in your own code.
Simply, because it would be redundant.
You should trust the developers of the library to (continuously) test their code, so you do not have to do it.
If you have tests defined in your own code, you should have a test collector (e.g. pytest) descend into all files of your project structure and run these.
You would end up testing all doctests in used libraries, which takes a lot of time. So the decision to ignore imported doctests is very sane.

Cucumber #Before questions

Okay so i'm not sure what i'm doing wrong but i have my project setup like this:
Top level package/
Feature package that contains one feature file/
Page package that contains one page class/
Steps package that contains one step page./
Utils package that contains runner class and a "hook" class + a class that just contains a web driver that gets passed around.
in the Hook class i have method annotated with #Before. Now if i go into the feature file right click on a scenario and run it, the method in the hook class gets called np and everything is well.
If i go into my runner class and run the test from there, the method doesn't get called and the step methods in the Step class are being called first.
If i put a #Before method in the Step class this works fine, but i don't wanna duplicate my code, how do i work around this?
Edit: sorry i'm not sure why my indentation looks horrible.

How to use Spock from the Command Line

I am writing a set of groovy scripts to be used as part of a Jenkins Pipeline Library. Currently I am using plain old JUnit to test them but would like to switch to Spock. I simply run the tests from the command line by invoking the following groovy script.
import groovy.util.AllTestSuite
import junit.textui.TestRunner
System.setProperty(AllTestSuite.SYSPROP_TEST_DIR, "./tests")
System.setProperty(AllTestSuite.SYSPROP_TEST_PATTERN, "**/*Test.groovy")
TestRunner.run(AllTestSuite.suite())
I am trying to figure what the equivalent script would be to run Spock specifications. My first attempt was to switch the SYSPROP_TEST_PATTERN to "**/*Spec.groovy. I have one ...Spec.groovy file written and sitting under ./tests that looks like this:
#Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.3')
import spock.lang.*
class UtilsSpec extends Specification {
def "Just testing"() {
expect:
1 + 1 == 2
}
}
When I invoke my groovy script though I get:
java.lang.RuntimeException: Don't know how to treat
/SourcCode/jenkins/pipeline-utils/tests/JustTestingSpec.groovy as a
JUnit test
That makes sense. I need to be using Sputnik but I've looked at the Spock and Sputnik source, and the Spock example project but these all assume you are using maven or gradle. I can't figured out the right way to invoke Sputnik directly. Any ideas?
Even though what you ask is possible and BalRog has already suggested a solution, in the long run it is better if you just use Gradle or Maven to run your tests from command line.
All Jenkins tutorials you will encounter will talk about Maven and/or Gradle and thus it would make much more sense to use a build system than custom scripts.

Reserved Class Names in Groovy

If I have a class named Character.groovy (with no explicit constructors) and try to instantiate it, I get a message that says:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.lang.Character()
But if I change the class name to Characterr.groovy, then I am able to instantiate an object and use it as expected. So are there reserved words I can't use in Groovy classes? If so, why is Character one of them?
It's not a reserved class name, but there already is a class with that name (java.lang.Character) imported as the package java.lang gets imported automatically in java.
This can happen all the time, especially if you are a java developer and not used to get e.g. java.io package etc. autoimported for you by groovy (e.g. File) (see also What packages does 1) Java and 2) Groovy automatically import?)
There are three ways around it:
the java way: address your class with the full name, that is package and class name. e.g. org.myrpg.Character.
the groovy way: import the class with a new name. e.g. import org.myrgp.Character as RPGChar and use then RPGChar instead.
the zen way: more often than not, it is not worth the hastle and easier to just rename your class. if you tripped over this once, then the chance very high you will trip over this again and only things like #CompileStatic or an IDE may make notice you this at compile time or while writing it.
http://groovy.codehaus.org/Reserved+Words
Those are the reserved keywords
http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html
Character I believe is a object wrapper class in java which is why you can't use it. You can't use any name of java classes that are autoincluded in java

parseClass loadClass groovy

When using the GroovyClassLoader, when should I use loadClass and when should I call parseClass?
If I understand it, the first call to loadClass() will compile the script, and subsequent calls will use the cached class file rather than recompiling it.
But what about parseClass then?
The documentation for parseClass shows that it takes a File or a String containing Groovy code, and converts it into a class.
If the function is passed a File, then the GroovyClassLoader will cache this generated class, but if it is passed a String, it will not cache it.
The function loadClass (from the documentation) says:
loads a class from a file or a parent classloader.
What it basically does, is looks for the class already existing in the classLoader, and if it fails to find it, look for the script file on disk with the matching name.
Once this class is loaded, it will be cached. The next time you call loadClass, it will use this cached class unless you pass false for the preferClassOverScript. If you pass false, it will attempt locate the script on disk again, recompile the class if necessary.

Resources