[JVM] Parsing .feature files to json in java easily?

3,081 views
Skip to first unread message

Grant Freder

unread,
Jul 8, 2013, 5:54:00 PM7/8/13
to cu...@googlegroups.com
Hello,
 
I am developing a manual test execution user interface in Java using Swing that parses gherkin .feature files, guides the user through individual steps (e.g. Given this, or When that) and recording the result of the test manually (Passed, Failed, Pending) along with their comments, then exporting all of the results to various XML formats.  Everything is setup besides the parsing. I am currently manually creating my data structure, converting it to json using gson, altering the json manually to look like an output from a parser, then feeding it back into my program again thru gson. I was hoping to use an existing parser.  I have been tooling around with your jar, and I can't seem to grasp if it is what I am looking for and how to best use it. 
 
Most directly, I was hoping to use your parser to parse .feature files and output the results to some sort of consistent, usable format (like json) so that I can setup my data structure and carry on with my program.  If you could please help me understand if cucumber's gherkin package is what I am looking for, it would be greatly appreciated.  And if so, please help me understand how I can best use it for what I would like to do.
 
Sincerely,
Grant Freder

Pranas Baliuka

unread,
Jul 8, 2013, 8:44:59 PM7/8/13
to cu...@googlegroups.com

aslak hellesoy

unread,
Jul 8, 2013, 9:40:57 PM7/8/13
to Cucumber Users
Yes, the gherkin library is indeed the right thing to use.
 
 And if so, please help me understand how I can best use it for what I would like to do.
 

Try this:

    StringBuilder json = new StringBuilder();
    JSONFormatter formatter = new JSONFormatter(json);
    Parser parser = new Parser(formatter);
    Lexer lexer = new En(parser);
    lexer.scan(theGherkinSource);

Aslak
 
Sincerely,
Grant Freder

--
-- Rules --
 
1) Please prefix the subject with [Ruby], [JVM] or [JS].
2) Please use interleaved answers http://en.wikipedia.org/wiki/Posting_style#Interleaved_style
3) If you have a question, don't reply to an existing message. Start a new topic instead.
 
You received this message because you are subscribed to the Google Groups Cukes group. To post to this group, send email to cu...@googlegroups.com. To unsubscribe from this group, send email to cukes+un...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/cukes?hl=en
---
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Grant Freder

unread,
Jul 9, 2013, 11:27:40 AM7/9/13
to cu...@googlegroups.com
Aslak,
 
Thank you for helping me get started.  I am very happy to hear that this is what I was looking for.  Thanks for providing me with starter code...
 
    StringBuilder json = new StringBuilder();
    JSONFormatter formatter = new JSONFormatter(json);
    Parser parser = new Parser(formatter);
    Lexer lexer = new En(parser);
    lexer.scan(theGherkinSource);
 
FYI: I am using the 2.12.0/ jar.  I am running into some issues with the scan method.  It, according to the javadoc, "Lexes the source." and takes as an input, "source a string containing Gherkin source".
 
Knowing that "Single Gherkin source file contains a description of a single feature. Source files have .feature extension.", I was a bit confused on what the method was looking for.  Forgive me if I am making a easy mistake, but could you help me understand how to use this method?  Clearly, it isn't designed for a file path (which would be a little too convenient, ha).  I tried converting my .feature file into a String with lines separated by newline characters (\n) and fed the method. 
 
However, I kept getting...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
 at java.util.ArrayList.elementData(ArrayList.java:371)
 at java.util.ArrayList.get(ArrayList.java:384)
 at gherkin.parser.Parser.machine(Parser.java:173)
 at gherkin.parser.Parser.event(Parser.java:159)
 at gherkin.parser.Parser.feature(Parser.java:96)
 at gherkin.lexer.En.scan(En.java:749)
 at bddUImain.Test.main(Test.java:81)
 
I don't believe this has to do with the errors described here....but I may be wrong.
 
I have tried looking for a java example of parsing and json output, but only found your response to someone's request for a ruby method similar to
json_feature = awesome_method(::Rails.root + 'path/to/my.feature')
 
In your response, you included nice example code...
 
If you would be wiling to provide me with a similar example in java of parsing a gherkin file and saving the json result, or perhaps a little more detailed explanation of the code you provided me, it would be greatly appreciated.
 
Sincerely,
Grant Freder
 
 

aslak hellesoy

unread,
Jul 9, 2013, 11:48:12 AM7/9/13
to Cucumber Users
On Tue, Jul 9, 2013 at 10:27 AM, Grant Freder <gfr...@gmail.com> wrote:
Aslak,
 
Thank you for helping me get started.  I am very happy to hear that this is what I was looking for.  Thanks for providing me with starter code...
 
    StringBuilder json = new StringBuilder();
    JSONFormatter formatter = new JSONFormatter(json);
    Parser parser = new Parser(formatter);
    Lexer lexer = new En(parser);
    lexer.scan(theGherkinSource);
 
FYI: I am using the 2.12.0/ jar.  I am running into some issues with the scan method.  It, according to the javadoc, "Lexes the source." and takes as an input, "source a string containing Gherkin source".
 
Knowing that "Single Gherkin source file contains a description of a single feature. Source files have .feature extension.", I was a bit confused on what the method was looking for.  Forgive me if I am making a easy mistake, but could you help me understand how to use this method?  Clearly, it isn't designed for a file path (which would be a little too convenient, ha).  I tried converting my .feature file into a String with lines separated by newline characters (\n) and fed the method. 
 
However, I kept getting...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
 at java.util.ArrayList.elementData(ArrayList.java:371)
 at java.util.ArrayList.get(ArrayList.java:384)
 at gherkin.parser.Parser.machine(Parser.java:173)
 at gherkin.parser.Parser.event(Parser.java:159)
 at gherkin.parser.Parser.feature(Parser.java:96)
 at gherkin.lexer.En.scan(En.java:749)
 at bddUImain.Test.main(Test.java:81)
 
I don't believe this has to do with the errors described here....but I may be wrong.
 

No those are unrelated.
 
I have tried looking for a java example of parsing and json output, but only found your response to someone's request for a ruby method similar to
json_feature = awesome_method(::Rails.root + 'path/to/my.feature')
 
In your response, you included nice example code...
 
If you would be wiling to provide me with a similar example in java of parsing a gherkin file and saving the json result, or perhaps a little more detailed explanation of the code you provided me, it would be greatly appreciated.
 

Sorry, the example above was from (my bad) memory. This should work:

    String path = ...
    String gherkin = FixJava.readReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
    StringBuilder json = new StringBuilder();
    JSONFormatter formatter = new JSONFormatter(json);
    Parser parser = new Parser(formatter);
    parser.parse(gherkin, path, 0);
    
    System.out.println(json); // Gherkin source as JSON

The gherkin argument should be the *contents* of a .feature file. The parser only uses the path argument to report parsing errrors, it doesn't attempt to actually read the contentsfrom the path. That's why you have to read the contents yourself. That's what the readReader helper method does.

Hope this helps,

Aslak

Grant Freder

unread,
Jul 9, 2013, 12:22:45 PM7/9/13
to cu...@googlegroups.com
Thank you for the more complete explanation Aslak.  It is still not working properly.  If you wouldn't mind working with me to a solution, again, it would be greatly appreciated.

This is my code...
 
package bddUImain;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import gherkin.formatter.JSONFormatter;
import gherkin.parser.Parser;
import gherkin.util.FixJava;
public class Test {
 
public static void main(String[] args) throws IOException {
 
{
   
String path = ....
   
String gherkin = FixJava.readReader(new InputStreamReader(
     
new FileInputStream(path), "UTF-8"));
   
System.out.println("gherkin...\n" + gherkin);

   
StringBuilder json = new StringBuilder();

   
System.out.println("json: '" + json + "'");

   
JSONFormatter formatter = new JSONFormatter(json);

   
System.out.println("formatter: "+formatter.toString());

   
Parser parser = new Parser(formatter);

   
System.out.println("parser: " + parser.toString());
   parser
.parse(gherkin, path, 0);
   
System.out.println("json: '" + json + "'"); // Gherkin source as JSON
 
}
 
}
}

 
 
 
The resulting output is this...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

gherkin...

 

 


Feature: Testing assorted things

As a user of this computer

I want to perform basic functionalities of Windows

So that I can perform more advanced tasks. 

 
Meta: @author Grant 

 
Scenario: WMP

Given a windows media player

When I double click on a song

Then I should hear that song playing



Scenario Outline: Dividing numbers

Given a Microsoft calculator

When I enter <n1> and divide it by <n2>

Then the displayed answer should be <result>


Examples:

| n1 | n2 | result |

| 30 | 5 | 6 |

| 0 | 100 | 0 |

| 12 | 0 | Cannot divide by zero |

| 10.2 | 1 | 10 |

json: ''

 

formatter: gherkin.formatter.JSONFormatter@15a3d6b

parser: gherkin.parser.Parser@1efb836

 

json: ''

 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I am unsure of what to make of this.  Everything seems to be in order, but obviously no json string is being saved.
 
 
Sincerely,
Grant

aslak hellesoy

unread,
Jul 9, 2013, 12:28:45 PM7/9/13
to Cucumber Users
I forgot, you need to call formatter.done(); formatter.close(); after parsing to write it out to the appendable you passed into the constructor.

Aslak

Grant Freder

unread,
Jul 9, 2013, 12:44:17 PM7/9/13
to cu...@googlegroups.com
Everything appears to be working as it should.  I am very excited to integrate this into my application.  If I have anymore questions, I shall ask them as a new post as they would be regarding a different topic.
 
Thank you very much for helping me through this initial setup.  I really appreciate it.
 
Grant
Reply all
Reply to author
Forward
Message has been deleted
0 new messages