Search code examples
seleniumselenium-webdriverjunitcucumbertestrail

How to connect Selenium Cucumber results to TestRail using JUnit


My issue is mainly to know how to populate TestRail results after Cucumber scenarios are run. I'm trying to have the results from my JUnit tests run set on an existing TestRail run. I have the APIClient and APIException as per this project. I then created this JUnit class also copying that same project. Not sure how to proceed now as first time using Cucumber and JUnit. Our project has also a Hooks class and a MainRunner if that helps?

public class Hooks {

public static WebDriver driver;

@Before
public void initializeTest() {

    System.out.println("Testing whether it starts before every scenario");

    driver = DriverFactory.startDriver();
}

}


import java.io.File;
@RunWith(Cucumber.class)
@CucumberOptions(
    features = {"src/test/java/clinical_noting/feature_files/"},
    glue = {"clinical_noting.steps", "clinical_noting.runner"},
    monochrome = true,
    tags = {"@current"},
    plugin = {"pretty", "html:target/cucumber", 
"json:target/cucumber.json", 
"com.cucumber.listener.ExtentCucumberFormatter:target/cucumber- 
reports/report.html"}
)

public class MainRunner {

@AfterClass
public static void writeExtentReport() {
    Reporter.loadXMLConfig(new File(FileReaderManager.getInstance().getConfigReader().getReportConfigPath())) 
;
}

}

Thanks for the help.

Update

Got TestRail to update when running the JUnit tests separately. Still not sure how to do it after the Cucumber scenario is run though? That's how it's working now:

public class JUnitProject {
private static APIClient client = null;
private static Long runId = 3491l;
private static String caseId = "";
private static int FAIL_STATE = 5;
private static int SUCCESS_STATE = 1;
private static String comment = "";
@Rule
public TestName testName = new TestName();

@BeforeClass
public static void setUp() {
    //Login to API
    client = testRailApiClient();
}

@Before
public void beforeTest() throws NoSuchMethodException {
    Method m = JUnitProject.class.getMethod(testName.getMethodName());
    if (m.isAnnotationPresent(TestRails.class)) {
        TestRails ta = m.getAnnotation(TestRails.class);
        caseId = ta.id();
    }
}

@TestRails(id = "430605")
@Test
public void validLogin() {
    comment = "another comment";
    Assert.assertTrue(true);
}

@Rule
public final TestRule watchman = new TestWatcher() {
    Map data = new HashMap();

    @Override
    public Statement apply(Statement base, Description description) {
        return super.apply(base, description);
    }

    @Override
    protected void succeeded(Description description) {
        data.put("status_id", SUCCESS_STATE);
    }

    // This method gets invoked if the test fails for any reason:
    @Override
    protected void failed(Throwable e, Description description) {
        data.put("status_id", FAIL_STATE);
    }

    // This method gets called when the test finishes, regardless of status
    // If the test fails, this will be called after the method above
    @Override
    protected void finished(Description description) {
        try {
            data.put("comment", comment);
            client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (APIException e) {
            e.printStackTrace();
        }
    };
};
}

And the annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) //on method level
public @interface TestRails {

String id() default "none";
}

Solution

  • Working now. Had to add the scenario param inside the before method and do the TestRail connection from there.

    @regressionM1 @TestRails(430605)
    Scenario: Verify the user can launch the application
    Given I am on the "QA-M1" Clinical Noting application
    Then I should be taken to the clinical noting page
    

    And

    public class Hooks {
    
    private static APIClient client = null;
    private static Long runId = 3491l;
    private static String caseId = "";
    private static int FAIL_STATE = 5;
    private static int SUCCESS_STATE = 1;
    private static String SUCCESS_COMMENT = "This test passed with Selenium";
    private static String FAILED_COMMENT = "This test failed with Selenium";
    @Rule
    public TestName testName = new TestName();
    
    public static WebDriver driver;
    
    @Before
    public void initializeTest() {
        client = testRailApiClient();
    
        System.out.println("Testing whether it starts before every scenario");
    
        driver = DriverFactory.startDriver();
    }
    
    @After()
    public void tearDown(Scenario scenario) {
        String caseIdSplit = "";
    
        for (String s : scenario.getSourceTagNames()) {
            if (s.contains("TestRail")) {
                caseIdSplit = s.substring(11, 17); // Hardcoded for now as all the ids have 6 characters
                System.out.println("Testing whether the browser closes after every scenario" + caseIdSplit);
            }
        }
    
        caseId = caseIdSplit;
        Map data = new HashMap();
    
        if (!scenario.isFailed()) {
            data.put("status_id", SUCCESS_STATE);
            data.put("comment", SUCCESS_COMMENT);
    
        } else if (scenario.isFailed()) {
    
            data.put("status_id", FAIL_STATE);
            data.put("comment", SUCCESS_COMMENT);
        }
    
        try {
            client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (APIException e) {
            e.printStackTrace();
        }
    }
    
    }
    

    Update Wrote a post on this here