I have a Groovy class with a single static method:
class ResponseUtil {
static String FormatBigDecimalForUI (BigDecimal value){
(value == null || value <= 0) ? '' : roundHalfEven(value)
}
}
It has a test case or few:
#Test
void shouldFormatValidValue () {
assert '1.8' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(1.7992311))
assert '0.9' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0.872342))
}
#Test
void shouldFormatMissingValue () {
assert '' == ResponseUtil.FormatBigDecimalForUI(null)
}
#Test
void shouldFormatInvalidValue () {
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0))
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0.0))
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(-1.0))
}
This results in 6/12 branches covered according to Sonar/JaCoCo:
So I've changed the code to be more...verbose. I don't think the original code is "too clever" or anything like that, but I made it more explicit and clearer. So, here it is:
static String FormatBigDecimalForUI (BigDecimal value) {
if (value == null) {
''
} else if (value <= 0) {
''
} else {
roundHalfEven(value)
}
}
And now, without having changed anything else, Sonar/JaCoCo report it to be fully covered:
Why is this the case?
I don't know if it applies to your concrete example, but keep in mind that code coverage tools typically don't work well for alternative JVM languages unless they support them explicitly. This is because virtually all of those languages generate extra byte code that may only get executed in certain cases. For example, Groovy might generate byte code for a slow path and a fast path, and might decide between them automatically, without the user having a say.
The situation might improve with Groovy 3.0, which will be designed around Java invokedynamic, meaning that less "magic" byte code will have to be generated. Meanwhile, I've heard that Clover has explicit Groovy support, although I don't know how up-to-date it is.
So, as it turns out, the Jacoco plugin for Sonar explicitly looks for Java code. I know this, as I debugged through it. It decodes the jacoco exec file and assumes any file is a JavaFile, which it doesn't find, and then says you have no coverage information.
Because of this, I grabbed the source code to the Jacoco plugin (it vanished from their Subversion repository, and never appeared on Github that I could find) and folded it into a new Groovy plugin. My updated one uses Codenarc 0.18.1 (which increases the Narc's from 32 to 305) and recognizes any kind of Jacoco file - the code in the existing plugin is unnecessarily wrong.
The source is here: https://github.com/rvowles/sonar-groovy - just build it and put it in your extensions/plugins directory.
Related
I have a Groovy class with a single static method:
class ResponseUtil {
static String FormatBigDecimalForUI (BigDecimal value){
(value == null || value <= 0) ? '' : roundHalfEven(value)
}
}
It has a test case or few:
#Test
void shouldFormatValidValue () {
assert '1.8' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(1.7992311))
assert '0.9' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0.872342))
}
#Test
void shouldFormatMissingValue () {
assert '' == ResponseUtil.FormatBigDecimalForUI(null)
}
#Test
void shouldFormatInvalidValue () {
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0))
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(0.0))
assert '' == ResponseUtil.FormatBigDecimalForUI(new BigDecimal(-1.0))
}
This results in 6/12 branches covered according to Sonar/JaCoCo:
So I've changed the code to be more...verbose. I don't think the original code is "too clever" or anything like that, but I made it more explicit and clearer. So, here it is:
static String FormatBigDecimalForUI (BigDecimal value) {
if (value == null) {
''
} else if (value <= 0) {
''
} else {
roundHalfEven(value)
}
}
And now, without having changed anything else, Sonar/JaCoCo report it to be fully covered:
Why is this the case?
I don't know if it applies to your concrete example, but keep in mind that code coverage tools typically don't work well for alternative JVM languages unless they support them explicitly. This is because virtually all of those languages generate extra byte code that may only get executed in certain cases. For example, Groovy might generate byte code for a slow path and a fast path, and might decide between them automatically, without the user having a say.
The situation might improve with Groovy 3.0, which will be designed around Java invokedynamic, meaning that less "magic" byte code will have to be generated. Meanwhile, I've heard that Clover has explicit Groovy support, although I don't know how up-to-date it is.
So, as it turns out, the Jacoco plugin for Sonar explicitly looks for Java code. I know this, as I debugged through it. It decodes the jacoco exec file and assumes any file is a JavaFile, which it doesn't find, and then says you have no coverage information.
Because of this, I grabbed the source code to the Jacoco plugin (it vanished from their Subversion repository, and never appeared on Github that I could find) and folded it into a new Groovy plugin. My updated one uses Codenarc 0.18.1 (which increases the Narc's from 32 to 305) and recognizes any kind of Jacoco file - the code in the existing plugin is unnecessarily wrong.
The source is here: https://github.com/rvowles/sonar-groovy - just build it and put it in your extensions/plugins directory.
I have plugins and i need to test, that any plugin fits to some specification. One of these cases is to check whether some interface exists in assembly (need to reflect from assembly).
I'd like to create some console application which will take plugin as an argument and check it.
This application will contain a set of tests, that will be configured by a passed argument. And the test runner which will produce xml report to output.
Is there better solution?
Update.
In my console application i call:
static int Main(string[] args)
{
CoreExtensions.Host.InitializeService();
var runner = new SimpleTestRunner();
var testPackage = new TestPackage(Assembly.GetExecutingAssembly().FullName);
string loc = Assembly.GetExecutingAssembly().Location;
testPackage.Assemblies.Add(loc);
if (runner.Load(testPackage))
{
var result = runner.Run(new NullListener(), new AllTestsFilter(), false, LoggingThreshold.Off);
var buffer = new StringBuilder();
new XmlResultWriter(new StringWriter(buffer)).SaveTestResult(result);
Console.Write(buffer.ToString());
return result.IsSuccess
? 0
: -1;
}
return -1;
}
In this soultion i have tests, but i need to pass arguments from command line to this tests through runner..
Probably you can use the TestCaseSource attribute: http://nunit.org/index.php?p=testCaseSource&r=2.6.3
Inside the test case source property you can enumerate the assemblies to test: NUnit will take care to generate a parametric test for each value.
Regarding the command line execution, you can use nunit-console.exe. You can get it here: http://www.nuget.org/packages/NUnit.Runners/
Hope it helps.
solved this problem by creation simple console application without NUnit.. Just return code -1/0
I am developing cucumber scenarios using Cucumber JVM (Groovy) in intellij. Things are much better than doing the same in eclipse I must say.
I'd like to resolve one small problem to make things even better for my team. But since I am new to Intellij, I need help with the following please:
When I am in a step def file (groovy), Intellij can't seem to see variables and methods defined in the cucumber "World" object. So don't get IDE support (auto-complete, etc) for those which is a bit annoying. How can I fix that?
IntelliJ IDEA expects an object inside World closure. So, you could define the folloing block in EACH step definitions file:
World {
new MockedTestWorld()
}
MockedTestWorld.groovy:
class MockedTestWorld implements TestWorld {
#Lazy
#Delegate
#SuppressWarnings("GroovyAssignabilityCheck")
private TestWorld delegate = {
throw new UnsupportedOperationException("" +
"Test world mock is used ONLY for syntax highlighting in IDE" +
" and must be overridden by concrete 'InitSteps.groovy' implementation.")
}()
}
To cleanup duplicated world definitions we use last-glue initializers and a bit of copy-paste:
real/InitSteps.groovy
def world
GroovyBackend.instance.#worldClosures.clear()
GroovyBackend.instance.registerWorld {
return world ?: (world = new RealTestWorld1()) // Actual initialization is much longer
}
legacy/InitSteps.groovy
def world
GroovyBackend.instance.#worldClosures.clear()
GroovyBackend.instance.registerWorld {
return world ?: (world = new LegacyTestWorld1())
}
Finally, run configurations would be like this (with different glues):
// Real setup
glue = { "classpath:test/steps", "classpath:test/real", },
// Legacy setup
glue = { "classpath:test/steps", "classpath:test/legacy", },
How do I print a Groovy stack trace? The Java method, Thread.currentThread().getStackTrace() produces a huge stack trace, including a lot of the Groovy internals. I'm seeing a function called twice from a StreamingMarkupBuilder that looks like it should only be called once and I would like to see why Groovy thinks it should be calling it twice.
Solution:
org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Exception()).printStackTrace()
Original answer:
A Google search returns the following information:
Apparently, there is a method in org.codehaus.groovy.runtime.StackTraceUtils called printSanitizedStackTrace. There isn't much documentation for the method, though there is a method called sanitize which is described as
remove all apparently groovy-internal
trace entries from the exception
instance This modifies the original
instance and returns it, it does not
clone
So I would try org.codehaus.groovy.runtime.StackTraceUtils.printSanitizedStackTrace(Throwable t) (it is static)
and see if that works for you.
I found this questions when searching for "spock print full stack trace".
My unit tests are written in Groovy, using the Spock testing framework and they're run in the context of a Gradle build.
The fix for me was as simple as adding exceptionFormat = 'full' to my Gradle test task specification:
test {
testLogging {
exceptionFormat = 'full'
}
}
I have designed this simple code for stack trace printing, based on artificial simulation of a NullPointerException.
This code produces the same output in both modes: from a Jenkinsfile (Pipeline) and from a normal .groovy script in a command line.
def getStackTrace() {
try {
null.class.toString() // simulate NPE
} catch (NullPointerException e) {
return e.getStackTrace()
}
return null
}
def printStackTrace() {
def stackTraceStr = ""
def callingFuncFound = false
for (StackTraceElement ste : getStackTrace()) {
if (callingFuncFound) {
stackTraceStr += ste.toString() + '\n'
}
if (!callingFuncFound && ste.toString().startsWith(this.class.name + '.printStackTrace(')) {
callingFuncFound = true
}
}
println(stackTraceStr)
}
Some explanations:
The output is concatenated into a single string to avoid being mixed with "[Pipeline] echo" message prefix of Jenkins Pipeline's println()).
The number of "unnecessary" upper stack trace elements related to the NPE is different in Jenkinsfile and in a normal command line. This is why I calculate callingFuncFound and don't use just something like e.getStackTrace()[2..-1] to skip them.
As new to groovy...
I'm trying to replace the java idiom for event listeners, filters, etc.
My working code in groovy is the following:
def find() {
ODB odb = ODBFactory.open(files.nodupes); // data nucleus object database
Objects<Prospect> src = odb.getObjects(new QProspect());
src.each { println it };
odb.close();
}
class QProspect extends SimpleNativeQuery {
public boolean match(Prospect p) {
if (p.url) {
return p.url.endsWith(".biz");
}
return false;
}
}
Now, this is far from what I'm used to in java, where the implementation of the Query interface is done right inside the odb.getObjects() method. If I where to code "java" I'd probably do something like the following, yet it's not working:
Objects<Prospect> src = odb.getObjects( {
boolean match(p) {
if (p.url) {
return p.url.endsWith(".biz");
}
return false;
}
} as SimpleNativeQuery);
Or better, I'd like it to be like this:
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
However, what groovy does it to associate the "match" method with the outer script context and fail me.
I find groovy... groovy anyways so I'll stick to learning more about it. Thanks.
What I should've asked was how do we do the "anonymous" class in groovy. Here's the java idiom:
void defReadAFile() {
File[] files = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.getPath().endsWith(".biz");
}
});
}
Can groovy be as concise with no additional class declaration?
I think it would have helped you to get answers if you'd abstracted the problem so that it didn't rely on the Neodatis DB interface -- that threw me for a loop, as I've never used it. What I've written below about it is based on a very cursory analysis.
For that matter, I've never used Groovy either, though I like what I've seen of it. But seeing as no one else has answered yet, you're stuck with me :-)
I think the problem (or at least part of it) may be that you're expecting too much of the SimpleNativeQuery class from Neodatis. It doesn't look like it even tries to filter the objects before it adds them to the returned collection. I think instead you want to use org.neodatis.odb.impl.core.query.criteria.CriteriaQuery. (Note the "impl" in the package path. This has me a bit nervous, as I don't know for sure if this class is meant to be used by callers. But I don't see any other classes in Neodatis that allow for query criteria to be specified.)
But instead of using CriteriaQuery directly, I think you'd rather wrap it inside of a Groovy class so that you can use it with closures. So, I think a Groovy version of your code with closures might look something like this:
// Create a class that wraps CriteriaQuery and allows you
// to pass closures. This is wordy too, but at least it's
// reusable.
import org.neodatis.odb.impl.core.query.criteria;
class GroovyCriteriaQuery extends CriteriaQuery {
private final c;
QProspect(theClosure) {
// I prefer to check for null here, instead of in match()
if (theClosure == null) {
throw new InvalidArgumentException("theClosure can't be null!");
}
c = theClosure;
}
public boolean match(AbstractObjectInfo aoi){
//!! I'm assuming here that 'aoi' can be used as the actual
//!! object instance (or at least as proxy for it.)
//!! (You may have to extract the actual object from aoi before calling c.)
return c(aoi);
}
}
// Now use the query class in some random code.
Objects<Prospect> src = odb.getObjects(
new GroovyCriteriaQuery(
{ it.url.endsWith(".biz") }
)
)
I hope this helps!
I believe your real question is "Can I use closures instead of anonymous classes when calling Java APIs that do not use closures". And the answer is a definite "yes". This:
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
should work. You write "However, what groovy does it to associate the "match" method with the outer script context and fail me". How exactly does it fail? It seems to me like you're having a simple technical problem to get the solution that is both "the groovy way" and exactly what you desire to work.
Yep, thanks y'all, it works.
I also found out why SimpleNativeQuery does not work (per Dan Breslau).
I tried the following and it worked wonderfully. So the idiom does work as expected.
new File("c:\\temp").listFiles({ it.path.endsWith(".html") } as FileFilter);
This next one does not work because of the neodatis interface. The interface does not enforce a match() method! It only mentions it in the documentation yet it's not present in the class file:
public class SimpleNativeQuery extends AbstactQuery{
}
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
In the above, as the SimpleNativeQuery does not have a match() method, it makes it impossible for the groovy compiler to identify which method in the SimpleNativeQuery should the closure be attached to; it then defaults to the outer groovy script.
It's my third day with groovy and I'm loving it.
Both books are great:
- Groovy Recipes (Scott Davis)
- Programming Groovy (Venkat Subramaniam)