Suppose we have a Spock specification class like below.
class SomeFeature extends Specification {
def "some scenario"() {
given: "some resource"
def resource = someResource()
when: "some action is taken"
someAction()
then: "some condition must be met"
true == someCondition()
}
}
How can I extract the BDD meta-statements like some scenario, given, when, then? It is straightforward to process the source file, but I am wondering if it is possible to use reflection to achieve that.
BTW, the motivation to get that information is to facilitate the communication between product owner and developer, such that the product owner can know what behaviors have been implemented and verified without looking at the source code.
Thank you very much.
In the cold hard light of day, there are some issues with this.
It's probably quite brittle and would need sorting out to handle different cases and formats (unrolled descriptions? helper methods? parameterised descriptions?)
It will just blindly dump out everything even if the test is never executed.
I think a much better and more stable solution would be the one in #PeterNiederwieser's comment above.
I'll leave this here for prosperity though, as it's quite a good example of how to generate an AST from some Groovy code as a String...
I don't think reflection will help, as it won't get you the contents of the methods.
You can do it by generating an AST from the source code, and then walking it looking for the nodes of interest.
So given the code in a String like so:
def code = '''import spock.*
class SomeFeature extends Specification {
def "some scenario"() {
given: "some resource"
def resource = someResource()
when: "some action is taken"
someAction()
then: "some condition must be met"
true == someCondition()
}
def "another"() {
given: 'a value 1'
def value = 1
then: '1 == 1'
value == 1
}
}'''
You can generate an AST:
import org.codehaus.groovy.antlr.*
import org.codehaus.groovy.antlr.parser.*
def ast = new GroovyRecognizer(
new GroovyLexer(
new StringReader( code ) ).plumb() ).with { p ->
p.compilationUnit()
p.AST
}
And then you can do something like this (this is probably not the cleanest way of doing it, I was under time constraints) ;-)
while( ast ) {
if( ast.type == GroovyTokenTypes.CLASS_DEF ) {
def child = ast.firstChild.nextSibling
println "Specification '${child.text}'"
while( child && child.type != GroovyTokenTypes.OBJBLOCK ) {
child = child.nextSibling
}
if( child ) {
child = child.firstChild
while( child ) {
if( child.type == GroovyTokenTypes.METHOD_DEF ) {
def method = child.firstChild
println " Scenario '${method.nextSibling?.nextSibling?.text}'"
while( method ) {
if( method.type == GroovyTokenTypes.SLIST ) {
def statements = method.firstChild
while( statements ) {
if( statements.type == GroovyTokenTypes.LABELED_STAT ) {
def label = statements.firstChild
println " ${label.text.toUpperCase()} '${label.nextSibling?.firstChild?.text}'"
}
statements = statements.nextSibling
}
}
method = method.nextSibling
}
}
child = child.nextSibling
}
}
}
ast = ast.nextSibling
}
That gives me the output:
Specification 'SomeFeature'
Scenario 'some scenario'
GIVEN 'some resource'
WHEN 'some action is taken'
THEN 'some condition must be met'
Scenario 'another'
GIVEN 'a value 1'
THEN '1 == 1'
Hope it helps...
Related
Currently, I have the following code that works:
//in class Bar
public Foo getFooIfItIsPresent(String param) {
Optional<Foo> result = loadOptionalFoo(param);
if (result.isPresent()) {
return result.get();
} else {
return null;
}
// main driver code
Foo foo = Bar.getFooIfItIsPresent(param);
if (foo != null) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
System.out.println(foo.getSomething() + foo.getSomethingElse());
}
This is kind of ugly, because I am checking for null explicitly; in addition, I have a convoluted function getFooIfItIsPresent that exists for the sole purpose of the isPresent() dance. I would want to do something like:
Bar.loadOptionalFoo(param).ifPresent((foo) -> {
// Print, or whatever I wanna do!
System.out.println(foo.getSomething() + foo.getSomethingElse());
});
I know this doesn't compile. There's been a very similar question, and I've tried a bunch of stuff, but the compiler complains. Eg:
Bar.loadOptionalFoo(week).map(foo -> {
// Print, or whatever I wanna do!
System.out.println(foo.getSomething() + foo.getSomethingElse());
}).filter(Objects::nonNull);
Yes, the code above is nonsensical, but I can't seem to wrap my head around getting an elegant solution for this, so a bit of help would be much appreciated!
tl;dr
The code you showed saying “I know this doesn't compile” actually should compile. That code is your solution.
Using similar code, see this method:
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( DayOfWeek.WEDNESDAY ); // Silly implementation for demonstration.
}
…called like this:
this.getFavoriteDayOfWeek().ifPresent(
( DayOfWeek dow ) -> { … dow.get() … }
);
…run live successfully at IdeOne.com.
Keep in mind that an Optional is its own object, wrapping some other object as its payload. So be careful about your type declarations: Optional<DayOfWeek> someVar versus DayOfWeek someVar.
Return the Optional
If a null is an acceptable value in your domain, then return the Optional. Returning a null unwrapped from within an Optional defeats the purpose of an Optional.
The purpose of an Optional is to signal to the calling method that a null is indeed a valid possibility. The type system of Java is being used to remind the calling programmer to code for the possibility of a null. An Optional object is like a big safety-orange traffic sign saying: “Beware: possible NULL ahead”.
Returning just null unwrapped from within an Optional adds no value, and makes for brittle code.
The code shown in the Question is jumping through extra hoops needlessly, just introducing an extra level of indirection with no benefit. The calling method should indeed receive an Optional if a payload of null is a valid result.
So this:
//in class Bar
public Foo getFooIfItIsPresent(String param) {
Optional<Foo> result = loadOptionalFoo(param);
if (result.isPresent()) {
return result.get();
} else {
return null;
}
// main driver code
Foo foo = Bar.getFooIfItIsPresent(param);
if (foo != null) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
System.out.println(foo.getSomething() + foo.getSomethingElse());
}
…should be:
//in class Bar
// ➥ Delete this method `getFooIfItIsPresent`. Adds no value.
// public Foo getFooIfItIsPresent(String param)
…and…
// main driver code
Optional<Foo> result = someBar.loadOptionalFoo( param );
if ( result.isPresent() ) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
Foo foo = result.get() ; // Calling `get` is safe because we checked for null in the `if … isPresent` line above.
System.out.println( foo.getSomething() + foo.getSomethingElse() ) ;
}
Notice how we call Optional::get only after checking for null by calling Optional::ifPresent.
The Optional class offers various methods if you want to address the if else condition where the Optional is empty with no Foo object present. See methods such as orElse, orElseGet, and orElseThrow.
Your problematic code should indeed compile
You said this code does not compile:
Bar.loadOptionalFoo(param).ifPresent((foo) -> {
// Print, or whatever I wanna do!
System.out.println(foo.getSomething() + foo.getSomethingElse());
});
Actually, that code should compile. It is perfectly reasonable to do, another variation of what I showed as a solution above.
Here is a similar example. I make the method getFavoriteDayOfWeek which returns an Optional< DayOfWeek > using the DayOfWeek enum class built into Java. If a favorite day is registered, the method returns an Optional holding a DayOfWeek object. If no favorite has yet been determined, the method returns an empty Optional. Here is our dummy version of that method.
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( DayOfWeek.WEDNESDAY );
}
Calling that method using code similar to your code:
this.getFavoriteDayOfWeek().ifPresent(
( DayOfWeek dayOfWeek ) -> {
// Print, or whatever I wanna do!
System.out.println( dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) );
}
);
When run:
mercredi
INFO - Done running demo.
You can change the WEDNESDAY object with null to experiment.
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( null );
}
When run, we see that the System.out.println( dayOfWeek.getDisplayName(… code is never called because the conditional test for our Optional<DayOfWeek> actually containing a DayOfWeek object (ifPresent) was not met. We see output only from our second System.out.println, for "Done running".
INFO - Done running demo.
See this code run live at IdeOne.com.
Making an Optional
The body of your Question seems to be asking about extracting a value from an Optional. I showed that above.
The title of your Question seems to be about wrapping a value in an Optional.
If you know you want to return a null, return Optional.empty().
If returning something that may or may not be null, return Optional.ofNullable( x ).
If returning something that should definitely not be null in that situation, return Optional.of( x ). That method throws NullPointerException if the value is null. Use this method when the presence of a null means something went very wrong with your app.
A tip, by the way, after seeing your use of if (foo != null) {:
If you do need to test for a null, I suggest instead of using x != null or x == null that you instead use the Objects class methods, Objects.nonNull( Object obj ) and Objects.isNull( Object obj ), respectively.
Even better, in a situation where the presence of a null in intolerable, meaning a major unexpected failure in your code, call Objects.requireNonNull( T obj ). This method throws NullPointerException if receiving a null. Even better, this method returns the object passed. This makes it perfect for assigning passed arguments to other variables.
public void doSomething( final Fruit fruit , final DayOfWeek dayOfWeek )
{
this.fruit = Objects.requireNonNull( fruit ) ;
this.dayOfWeek = Objects.requireNonNull( dayOfWeek ) ;
}
Last tip: Java 14 brings more helpful NullPointerException objects, better pinpointing the place of failure. See JEP 358: Helpful NullPointerExceptions.
I fails to understand your problem with ifPresent since you are not even handling the case where the value is empty: why not use a method reference?
Have some method take a Foo parameter and do whatever:
class X {
private Optional<Foo> loadFoo(String name) {...}
private void consumeFoo(Foo foo) {...}
void doSomething(String name) {
this.loadFoo(name).ifPresent(this::consumeFoo);
}
}
Also you can do
return result.orElse(null);
Instead of:
if (result.isPresent()) {
return result.get();
} else {
return null;
}
I agree with Basil, but here's another possibility :
Bar.loadOptionalFoo(week)
.map(foo ->
String.format("%s %s",
foo.getSomething(),
foo.getSomethingElse()))
.ifPresent(System.out::println);
You can directly return null more elegantly, then have that null check :). Or if you don't want to have null check, than you can return Optional and do isPresent check
public Foo getFoo(String param) {
return Optional.ofNullable(loadOptionalFoo(param)).orElse(null);
}
Foo foo = Bar.getFoo(param);
if (foo != null) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
System.out.println(foo.getSomething() + foo.getSomethingElse());
}
I just started Kotlin so please be nice :)
I have a class that is responsible for fetching some data and notify the main activity that its need to update its UI.
So i have made a function in my DataProvider.kt :
fun getPeople(fromNetwork: Boolean, results: ((persons: Array<Person>, error: MyError?) -> Unit)) {
// do some stuff stuff
val map = hashMapOf(
"John" to "Doe",
"Jane" to "Smith"
)
var p = Person(map)
val persons: Array <Person> = arrayOf (p)
results(persons, null)
}
So i want to call this from my activity but i can't find the right syntax ! :
DataProvider.getPeople(
true,
results =
)
I have try many things but i just want to get my array of persons and my optional error so i can update the UI.
The goal is to perform async code in my data provider so my activity can wait for it.
Any ideas ? Thank you very much for any help.
This really depends on how you define the callback method. If you use a standalone function, use the :: operator. First (of course), I should explain the syntax:
(//these parenthesis are technically not necessary
(persons: Array<Person>, error: MyError?)//defines input arguments: an Array of Person and a nullable MyError
-> Unit//defines the return type: Unit is the equivalent of void in Java (meaning no return type)
)
So the method is defined as:
fun callback(persons: Array<CustomObject>, error: Exception?){
//Do whatever
}
And you call it like:
DataProvider.getPeople(
true,
results = this::callback
)
However, if you use anonymous callback functions, it's slightly different. This uses lambda as well:
getPeople(true, results={/*bracket defines a function. `persons, error` are the input arguments*/persons, error -> {
//do whatever
}})
Yes Kotlin has a great way of using callback functions which I will show you an example of how I use them below:
fun addMessageToDatabase(message: String, fromId: String, toId: String,
addedMessageSuccessHandler: () -> Unit,
addedMessageFailureHandler: () -> Unit) {
val latestMessageRef = mDatabase.getReference("/latest-messages/$fromId/$toId")
latestMessageRef.setValue(message).addOnSuccessListener {
latestMessageUpdateSuccessHandler.invoke()
}.addOnFailureListener {
latestMessageUpdateFailureHandler.invoke()
}
}
And finally you can utilise the new callbacks with the following code
databaseManager.updateLatestMessageForUsers(message, fromId, toId,
latestMessageUpdateSuccessHandler = {
// your success action
},
latestMessageUpdateFailureHandler = {
// your failure action
})
So basically when I successfully add a new row to my database I'm invoking a success or a failure response to the caller of the service. Hopefully this will help out someone.
I have my custom SonarQube plugIn up and running on a local SonarQube server and it works fine. Now I want to add more stuff to it. I'm interested in coding my own Sonar Rule which checks if the non deprecated constructor is used for one class.
Possible constructor calls:
#Deprecated
public ExampleClass(String a)
{
//deprecated/old/wrong stuff happening
}
public ExampleClass(String a, String b)
{
//correct stuff happening
}
I'm already at the state, that only Method notes will be visited.
Now I'm wondering how can I check which new ExampleClass expression is used?
Found a working solution.
Here's what I did:
set nodesToVisit to Tree.Kind.ASSIGNMENT
check if the expression is Tree.Kind.NEW_CLASS
check if identifier is ExampleClass.class.getSimpleName()
do my argument checks
Code:
AssignmentExpressionTree assignment = (AssignmentExpressionTree) tree;
if ( assignment.expression().is(Tree.Kind.NEW_CLASS) )
{
NewClassTreeImpl expression = (NewClassTreeImpl) assignment.expression();
IdentifierTreeImpl identifier = (IdentifierTreeImpl) expression.identifier();
if ( StringUtils.equals(identifier.name(), ExampleClass.class.getSimpleName()) )
{
ArgumentListTreeImpl arguments = (ArgumentListTreeImpl) expression.arguments();
if ( arguments.size() != 2 )
{
reportIssue(expression, "Use the 2 parameter constructor call when creating new ExampleClass objects!");
}
else if ( StringUtils.indexOfAny(arguments.get(1).symbolType().name(), POSSIBLE_PARAMETER_TYPES) == -1 )
{
reportIssue(expression, "The second parameter must be from type String");
}
}
}
If you find any improvement of my rule, please let me know. Thanks!
How do I go about evaluating logical expression like "VERB1 OR (VERB2 AND VERB3) OR (VERB4)" entered at runtime. VERB* are placeholder to evaluate certain conditions. For example, VERB1 might mean check for the existence of a record in database.
In expression "VERB1 OR (VERB2 AND VERB3) OR (VERB4)", other verbs should not be executed if VERB1 is true
EDIT: Example described at http://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language/ seems very similar to what I am trying to do. However, the optimization step (other verbs should not be executed if VERB1 is true) doesn't seem to be there.
If you can use || and && in place of AND and OR, you can just use groovy's missing property methods and the GroovyShell base class setting like so:
import org.codehaus.groovy.control.CompilerConfiguration
// The command to be executes
def command = "VERB1 || (VERB2 && VERB3) || (VERB4)"
// Set a base class for the GroovyShell
new CompilerConfiguration().with { compiler ->
compiler.scriptBaseClass = 'VerbHandlingBaseClass'
new GroovyShell( this.class.classLoader, new Binding(), compiler ).with { shell ->
// and evaluate the command
shell.evaluate( command )
}
}
abstract class VerbHandlingBaseClass extends Script {
boolean VERB1() {
System.out.println( 'CHECK THE DATABASE, RETURN FALSE' )
false
}
boolean VERB2() {
System.out.println( 'WRITE A LOG ENTRY RETURN TRUE' )
true
}
boolean VERB3() {
System.out.println( 'VALIDATE SOMETHING, RETURN TRUE' )
true
}
boolean VERB4() {
System.out.println( 'THIS WONT BE REACHED, AS VERB2 && VERB3 == true' )
true
}
def propertyMissing( String name ) {
"$name"()
}
}
That should print:
CHECK THE DATABASE, RETURN FALSE
WRITE A LOG ENTRY RETURN TRUE
VALIDATE SOMETHING, RETURN TRUE
You mentioned ANTLR in your tags: have you given this a go? You can create a full boolean grammar in ANTLR but it gets much harder when you get down to the level of how to evaluate the verbs.
If there is a small, fixed set of verbs which may be queried you can easily create a mapping between the verbs and the functions.
If there is a larger list of verbs, you may be able to use reflection to call specific methods to evaluate them.
If your verbs can include mathematical comparisons, this all gets a bit harder as you create a mathematical lexer and parser as well.
Without a more specific question and knowledge of what you have tried in ANTLR I'm not sure I can give you much more advice.
EDIT: Based on your comments, I'll add some more.
You can add parsing rules to your grammar:
boolean_or returns [boolean b]
: b1=boolean_and {$b = $b1.b;}
(OR b2=boolean_and {$b = $b || $b2.b;})*
;
boolean_atom returns [boolean b]
:
((numeric_comparison)=> b1=numeric_comparison {$b = $b1.b;}
| TRUE {$b = true;} | FALSE {$b = false;}
| s1=VERB {$b = evalVerb($s1.s);}
| LPAREN b1=boolean_expr RPAREN {$b = $b1.b;}
)
;
Thats a small part of a boolean parser I'm currently using. You can fill in the blanks.
And then call the parser using something like
ANTLRStringStream in = new ANTLRStringStream(booleanString);
ActionLexer lexer = new ActionLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
BooleanParser parser = new BooleanParser(tokens);
try {
return parser.eval();
} catch (Exception e) {
}
This doesn't account for your requirement of returning early, but I'm sure you can figure out how to do that.
This might not be the best way to do things, but its the way that I've gotten it to work for me in the past. Hope this helps.
We have an ArrayList of items in several classes which are giving me trouble every time I'd like to insert a new item into the list. It was a mistake on my part to have designed the classes in the way I did but changing the design now would be more headache than it's worth (bureaucratic waterfall model.) I should have anticipated format changes to the documents the customer was supplying us waterfall be damned.
I'd like to write a simple script in python which goes into a class, adds the item to the list, and then increments all retrievals for the following items. That doesn't sound very explanatory:
Foo extends Bar{
public Foo(){
m_Tags.add("Jane");
m_Tags.add("Bob");
m_Tags.add("Jim");
}
public String GetJane() { return m_ParsedValue.get( m_Tags.get(1) ); }
public String GetBob() { return m_ParsedValue.get( m_Tags.get(2) ); }
public String GetJim() { return m_ParsedValue.get( m_Tags.get(3) ); }
}
You see if I want to add a value between "Jane" and "Bob" I then have to increment the integers in the Get* functions. I just want to write a simple script in Python that does the work for me. Someone I very much respect suggested regex.
Edit:
Yes, LinkedHashMap. So simple, so easy and so not in the design specs now. I hate waterfall. Hate it with a passion. This whole bit was a "small" and "easy" part that "shouldn't take much time to design." I made mistakes. It's stuck in stone now.
You want your regular expression to be as flexible as the compiler will be with respect to whitespace between tokens. Doing so and mimicking whitespace usage makes the pattern pretty messy. The code below (sorry: Perl, not Python) edits your source files in-place.
#! /usr/bin/perl -i.bak
use warnings;
use strict;
my $template =
'^( public
String
Get)(\w+)( \( \) { return
m_ParsedValue . get \( m_Tags . get \( )(\d+)( \) \) ; } )$';
$template =~ s/ +/\\s*/g;
$template =~ s/(\r?\n)+/\\s+/g;
my $getter = qr/$template/x;
die "Usage: $0 after new-name source ..\n" unless #ARGV >= 3;
my $after = shift;
my $add = shift;
my $index;
while (<>) {
unless (/$getter/) {
print;
next;
}
my($abc,$name,$lmno,$i,$xyz) = ($1,$2,$3,$4,$5);
if (defined $index) {
print join "" => $abc, $name, $lmno, ++$index, $xyz;
}
else {
if ($name eq $after) {
$index = $i;
print; print join "" => $abc, $add, $lmno, ++$index, $xyz;
}
else { print; }
}
}
For example,
$ ./add-after Jane Foo code.java
$ cat code.java
Foo extends Bar{
public Foo(){
m_Tags.add("Jane");
m_Tags.add("Bob");
m_Tags.add("Jim");
}
public String GetJane() { return m_ParsedValue.get( m_Tags.get(1) ); }
public String GetFoo() { return m_ParsedValue.get( m_Tags.get(2) ); }
public String GetBob() { return m_ParsedValue.get( m_Tags.get(3) ); }
public String GetJim() { return m_ParsedValue.get( m_Tags.get(4) ); }
}
Don't do this with regexp. Create symbolic constants (using for example an enum) that map the names to numbers.
Comments about bad-practices apart - here is the code you asked in the language you asked for.
The best thing if you are keeping the system this way, probably would be to make these java files be automatically generated in the build process itself -- you 'd just keep a names list in a .txt file in the directory. This script is suitable to do that.
(It won't modify your files, it genrate new ones based on the template you posted here)
import re, sys
template = """Foo extends Bar{
public Foo(){
%s
}
%s
}
"""
tag_templ = """ m_Tags.add("%s");"""
getter_templ = """ public String GetJane() { return m_ParsedValue.get( m_Tags.get(%d) ); }"""
def parse_names(filename):
data = open(filename).read()
names = re.findall(r'm_Tags\.add\("(.*?)"', data)
return names
def create_file(filename, names):
tag_lines = [tag_templ % name for name in names]
getter_lines = [getter_templ % (i + 1) for i in range(len(names))]
code = template % ("\n".join(tag_lines), "\n".join(getter_lines))
file = open(filename,"wt")
file.write(code)
file.close()
def insert_name(after, new_name, names):
names.insert(names.index(after) + 1, new_name)
if __name__ == "__main__":
if len(sys.argv ) < 4:
sys.stderr.write("Usage: changer.py <filename> <name-before-insertion> <new-name>")
sys.exit(1)
filename, name_before, new_name = sys.argv[1:]
names = parse_names(filename)
insert_name(name_before, new_name, names)
create_file(filename, names)
I'm doing this (well, something very similar) right now, but using Excel and VBA macros. All of the Business Values are organized and ordered in a spreadsheet. I just have to click a button to generate the appropriate code for the selected cells, then copy-paste to the IDE. Better yet, I have several "code columns" for each row. Some of them generate queries, some XSL transformations, and some procedures. For one row of business data, I can get all three types of generated code very easily.
I found this (re-generate) to be MUCH easier than re-formatting the existing code I had.