Details

    • Type: Improvement Improvement
    • Status: Open Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 3.5.4
    • Fix Version/s: 3.x
    • Component/s: Core
    • Environment:
      JIRA v4.2
    • Number of attachments :
      0

      Description

      We are using JIRA to organise our stories. It would be nice to integrate the story files directly from JIRA, so you don't have to write them twice. At this moment we write the acceptance criteria for a story in JIRA and we copy them into our projects.

      My idea is to
      -extend the LoadFromUrl class to add the functionality to log into a page (like for google docs). Something like LoadFromSecuredUrl, LoadFromJira
      -then write a parser that extracts the fields from a story in JIRA as plain text like you propose it here http://jbehave.org/reference/stable/locating-stories.html

        Activity

        Hide
        Cristiano Gavião added a comment -

        Hi, I did this couple years ago. Actually I've used the Confluence instead but it is the same.
        But I don't think it is necessary anything more in Jbehave side other than the LoadFromURL.
        You just need to create a plugin with the built-in REST support. This plugin will capture the calling parameters and process it. The result of your call will be a string (you can bring one story or a set of), so you don't need to worry in create a parser in the client side.
        In client, you just need some abstract step class that connect to server calling the right http address with the right parameters.

        Show
        Cristiano Gavião added a comment - Hi, I did this couple years ago. Actually I've used the Confluence instead but it is the same. But I don't think it is necessary anything more in Jbehave side other than the LoadFromURL. You just need to create a plugin with the built-in REST support. This plugin will capture the calling parameters and process it. The result of your call will be a string (you can bring one story or a set of), so you don't need to worry in create a parser in the client side. In client, you just need some abstract step class that connect to server calling the right http address with the right parameters.
        Hide
        Olmo Rigolo added a comment -

        Thanks Cristiano.
        Your ideas helped me to implement a basic LoadFromJIRA.
        I use the atlassian.jira.rest.client.

        import java.net.URI;
        import java.net.URISyntaxException;

        import org.jbehave.core.io.ResourceLoader;
        import org.jbehave.core.io.StoryLoader;

        import com.atlassian.jira.rest.client.JiraRestClient;
        import com.atlassian.jira.rest.client.NullProgressMonitor;
        import com.atlassian.jira.rest.client.domain.Issue;
        import com.atlassian.jira.rest.client.internal.jersey.JerseyJiraRestClientFactory;

        /**

        • Loads data from JIRA fields "Narrative" and "Acceptance Criteria"
        • @author olmo.rigolo
        • */
          public class LoadFromJIRA implements ResourceLoader, StoryLoader {

        private final String narrativeFieldName = "Narrative";

        private final String scenariosFieldName = "Acceptance Criteria";

        private String storyId;

        private String location;

        private String username;

        private String password;

        private JiraRestClient restClient = null;

        final NullProgressMonitor pm = new NullProgressMonitor();

        /**

        • Configures the JIRA loader.
        • @param location The jira url
        • @param username The jira account username
        • @param password The jira account password
        • @param storyId The jira story id
          */
          public LoadFromJIRA(String location, String username, String password, String storyId) { this.location = location; this.password = password; this.username = username; this.storyId = storyId; }

        @Override
        public String loadStoryAsText(String storyPath)

        { return loadFromJira(this.storyId); }

        @Override
        public String loadResourceAsText(String resourcePath) { return loadFromJira(this.storyId); }

        private JiraRestClient connect(String location, String username, String password) {
        JerseyJiraRestClientFactory factory = new JerseyJiraRestClientFactory();
        restClient = null;
        try

        { restClient = factory.createWithBasicHttpAuthentication(new URI(location), username, password); }

        catch (URISyntaxException e)

        { e.printStackTrace(); }

        return restClient;
        }

        private String loadFromJira(String storyId) {
        if(this.restClient == null)

        { this.restClient = connect(location, username, password); }

        final Issue issue = restClient.getIssueClient().getIssue(storyId, pm);
        final String narrative = issue.getFieldByName(narrativeFieldName).getValue().toString();
        final String scenarios = issue.getFieldByName(scenariosFieldName).getValue().toString();

        StringBuilder sb = new StringBuilder();
        sb.append("Narrative:");
        sb.append(narrative);
        sb.append(scenarios);

        return sb.toString();
        }
        }

        -----------------
        Usage:
        Configuration configuration = new MostUsefulConfiguration()
        .useStoryLoader(new LoadFromJIRA("http://localhost/jira", "yourJiraUserName","yourJiraPassword", "JIRA-STORYID-112"))
        .useStoryReporterBuilder(new StoryReporterBuilder().withFormats(HTML));

        -----------------
        Ressources:
        jira rest client library
        http://confluence.atlassian.com/display/DOCSPRINT/The+Simplest+Possible+JIRA+REST+Examples
        https://studio.atlassian.com/wiki/display/JRJC/Tutorial

        Show
        Olmo Rigolo added a comment - Thanks Cristiano. Your ideas helped me to implement a basic LoadFromJIRA. I use the atlassian.jira.rest.client. import java.net.URI; import java.net.URISyntaxException; import org.jbehave.core.io.ResourceLoader; import org.jbehave.core.io.StoryLoader; import com.atlassian.jira.rest.client.JiraRestClient; import com.atlassian.jira.rest.client.NullProgressMonitor; import com.atlassian.jira.rest.client.domain.Issue; import com.atlassian.jira.rest.client.internal.jersey.JerseyJiraRestClientFactory; /** Loads data from JIRA fields "Narrative" and "Acceptance Criteria" @author olmo.rigolo */ public class LoadFromJIRA implements ResourceLoader, StoryLoader { private final String narrativeFieldName = "Narrative"; private final String scenariosFieldName = "Acceptance Criteria"; private String storyId; private String location; private String username; private String password; private JiraRestClient restClient = null; final NullProgressMonitor pm = new NullProgressMonitor(); /** Configures the JIRA loader. @param location The jira url @param username The jira account username @param password The jira account password @param storyId The jira story id */ public LoadFromJIRA(String location, String username, String password, String storyId) { this.location = location; this.password = password; this.username = username; this.storyId = storyId; } @Override public String loadStoryAsText(String storyPath) { return loadFromJira(this.storyId); } @Override public String loadResourceAsText(String resourcePath) { return loadFromJira(this.storyId); } private JiraRestClient connect(String location, String username, String password) { JerseyJiraRestClientFactory factory = new JerseyJiraRestClientFactory(); restClient = null; try { restClient = factory.createWithBasicHttpAuthentication(new URI(location), username, password); } catch (URISyntaxException e) { e.printStackTrace(); } return restClient; } private String loadFromJira(String storyId) { if(this.restClient == null) { this.restClient = connect(location, username, password); } final Issue issue = restClient.getIssueClient().getIssue(storyId, pm); final String narrative = issue.getFieldByName(narrativeFieldName).getValue().toString(); final String scenarios = issue.getFieldByName(scenariosFieldName).getValue().toString(); StringBuilder sb = new StringBuilder(); sb.append("Narrative:"); sb.append(narrative); sb.append(scenarios); return sb.toString(); } } ----------------- Usage: Configuration configuration = new MostUsefulConfiguration() .useStoryLoader(new LoadFromJIRA("http://localhost/jira", "yourJiraUserName","yourJiraPassword", "JIRA-STORYID-112")) .useStoryReporterBuilder(new StoryReporterBuilder().withFormats(HTML)); ----------------- Ressources: jira rest client library http://confluence.atlassian.com/display/DOCSPRINT/The+Simplest+Possible+JIRA+REST+Examples https://studio.atlassian.com/wiki/display/JRJC/Tutorial
        Hide
        Cristiano Gavião added a comment -

        Hi Olmo,

        glad to see that you could make it work. good job !

        If my memory is no falling in my case I've created one AnnotatedEmbedder for each group of stories of my customer system.
        so I've used annotations to setup the confluence server url and auth data as you did, but I've used StoryPath to pass more than one stories urls instead only one as you did...
        I've searched but couldn't find this code in my backup stuffs.. what shame

        cheers

        Show
        Cristiano Gavião added a comment - Hi Olmo, glad to see that you could make it work. good job ! If my memory is no falling in my case I've created one AnnotatedEmbedder for each group of stories of my customer system. so I've used annotations to setup the confluence server url and auth data as you did, but I've used StoryPath to pass more than one stories urls instead only one as you did... I've searched but couldn't find this code in my backup stuffs.. what shame cheers
        Hide
        Mauro Talevi added a comment -

        Very interesting work. Would you be able to provide this as separate maven module complete with its jira dependencies?

        Show
        Mauro Talevi added a comment - Very interesting work. Would you be able to provide this as separate maven module complete with its jira dependencies?
        Mauro Talevi made changes -
        Field Original Value New Value
        Fix Version/s 3.x [ 16979 ]
        Hide
        Lukasz Hanik added a comment -

        Hello,
        Thanks for great work! However I think the better solution would be to:
        1. have .story files within SVN,
        2. tag .story files (and/or scenarios within them) with JIRA issue id. E.g.
        Meta:
        @issue PROJECT-1,
        3. add functionality to JIRA to extract (from SVN .story files) all stories/scenarios tagged with the issue ID and put extracted text in 'Done Criteria' section of specific JIRA issue. I mean by that - all stories/scenarios with '@issue PROJECT-1' would be automatically extracted from their source files in SVN and displayed in JIRA issue named PROJECT-1.

        What do you think about it? Is it possible to achieve? What are disadvantages of this solution from your point of view?

        Show
        Lukasz Hanik added a comment - Hello, Thanks for great work! However I think the better solution would be to: 1. have .story files within SVN, 2. tag .story files (and/or scenarios within them) with JIRA issue id. E.g. Meta: @issue PROJECT-1, 3. add functionality to JIRA to extract (from SVN .story files) all stories/scenarios tagged with the issue ID and put extracted text in 'Done Criteria' section of specific JIRA issue. I mean by that - all stories/scenarios with '@issue PROJECT-1' would be automatically extracted from their source files in SVN and displayed in JIRA issue named PROJECT-1. What do you think about it? Is it possible to achieve? What are disadvantages of this solution from your point of view?
        Hide
        Mauro Talevi added a comment -

        Are you suggesting to write a Jira plugin that can parse the JBehave stories or to use the Jira Rest client to administer the issues?

        Show
        Mauro Talevi added a comment - Are you suggesting to write a Jira plugin that can parse the JBehave stories or to use the Jira Rest client to administer the issues?
        Hide
        Lukasz Hanik added a comment - - edited

        I'm suggesting to write a Jira plugin that can:
        1. parse the JBehave stories/scenarios (query based on meta information),
        2. display JBehave stories/scenarios inside 'Done Criteria' field of desired Jira issue(s).

        Usage example:
        I have ABC-1 issue in Jira. I have just prepared JBehave story file with 10 scenarios. Six of those scenarios have meta information - '@issue ABC-1'. I'm editing 'Done Criteria' field within issue ABC-1 in Jira. I'd like to use here Jira plugin/macro, where I can provide link to my SVN and search criteria (desired meta information - '@issue ABC-1'). Then Jira plugin/macro browse given SVN URL for provided meta information and display 6 scenarios marked with meta information '@issue ABC-1' (of course with appropriate narrative from .story file). It should be updated automatically during opening Jira issue to ensure that presented scenarios are up to date and complete (if somebody added new scenarios in the meanwhile).

        Update 2012-06-11:
        It could be even better to create JIRA plugin working as FishEye plugin. I mean - in all JIRA issues there would be 'Scenarios' tab within 'Activity' section (similar to 'Source' tab within 'Activity' section) which would connect to FishEye and list all scenarios with meta information related to currently opened JIRA issue (e.g. '@issue ABC-1').
        It would be better as it can be configured once per project (not per issue as suggested above) and connecting with previously defined repositories.
        What do you think about it?

        Show
        Lukasz Hanik added a comment - - edited I'm suggesting to write a Jira plugin that can: 1. parse the JBehave stories/scenarios (query based on meta information), 2. display JBehave stories/scenarios inside 'Done Criteria' field of desired Jira issue(s). Usage example: I have ABC-1 issue in Jira. I have just prepared JBehave story file with 10 scenarios. Six of those scenarios have meta information - '@issue ABC-1'. I'm editing 'Done Criteria' field within issue ABC-1 in Jira. I'd like to use here Jira plugin/macro, where I can provide link to my SVN and search criteria (desired meta information - '@issue ABC-1'). Then Jira plugin/macro browse given SVN URL for provided meta information and display 6 scenarios marked with meta information '@issue ABC-1' (of course with appropriate narrative from .story file). It should be updated automatically during opening Jira issue to ensure that presented scenarios are up to date and complete (if somebody added new scenarios in the meanwhile). Update 2012-06-11: It could be even better to create JIRA plugin working as FishEye plugin. I mean - in all JIRA issues there would be 'Scenarios' tab within 'Activity' section (similar to 'Source' tab within 'Activity' section) which would connect to FishEye and list all scenarios with meta information related to currently opened JIRA issue (e.g. '@issue ABC-1'). It would be better as it can be configured once per project (not per issue as suggested above) and connecting with previously defined repositories. What do you think about it?
        Hide
        Mauro Talevi added a comment -

        Hi Lukasz,

        it's surely an interesting proposition and complementary to any client-side one. Do you have any experience in writing a Jira or FishEye plugin? Any contribution would be welcome.

        Show
        Mauro Talevi added a comment - Hi Lukasz, it's surely an interesting proposition and complementary to any client-side one. Do you have any experience in writing a Jira or FishEye plugin? Any contribution would be welcome.
        Hide
        Lukasz Hanik added a comment -

        Hi Mauro,
        Unfortunately I have no experience in writing any plugin. I'm just QA

        Show
        Lukasz Hanik added a comment - Hi Mauro, Unfortunately I have no experience in writing any plugin. I'm just QA
        Hide
        Brian Repko added a comment -

        We might get some ideas on what this integration could look like from:

        https://confluence.atlassian.com/display/CONFEVAL/Integrate+JIRA+With+A+Test+Case+Manager

        or Requirement Mgmt or other Use Cases - Agile Development - there is a set of menus on the side to browse.

        Show
        Brian Repko added a comment - We might get some ideas on what this integration could look like from: https://confluence.atlassian.com/display/CONFEVAL/Integrate+JIRA+With+A+Test+Case+Manager or Requirement Mgmt or other Use Cases - Agile Development - there is a set of menus on the side to browse.

          People

          • Assignee:
            Unassigned
            Reporter:
            Olmo Rigolo
          • Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:

              Time Tracking

              Estimated:
              Original Estimate - 3 minutes
              3m
              Remaining:
              Remaining Estimate - 3 minutes
              3m
              Logged:
              Time Spent - Not Specified
              Not Specified