How to integrate Testrail with Karate Framework [duplicate] - karate

I am new to Java and using karate for API automation. I need help to integrate testrail with karate. I want to use tags for each scenario which will be the test case id (from testrail) and I want to push the result 'after the scenario'.
Can someone guide me on this? Code snippets would be more appreciated. Thank you!

I spent a lot of effort for this.
That's how I implement. Maybe you can follow it.
First of all, you should download the APIClient.java and APIException.java files from the link below.
TestrailApi in github
Then you need to add these files to the following path in your project.
For example: YourProjectFolder/src/main/java/testrails/
In your karate-config.js file, after each test, you can send your case tags, test results and error messages to the BaseTest.java file, which I will talk about shortly.
karate-config.js file
function fn() {
var config = {
baseUrl: 'http://111.111.1.111:11111',
};
karate.configure('afterScenario', () => {
try{
const BaseTestClass = Java.type('features.BaseTest');
BaseTestClass.sendScenarioResults(karate.scenario.failed,
karate.scenario.tags, karate.info.errorMessage);
}catch(error) {
console.log(error)
}
});
return config;
}
Please dont forget give tag to scenario in Feature file.
For example #1111
Feature: ExampleFeature
Background:
* def conf = call read('../karate-config.js')
* url conf.baseUrl
#1111
Scenario: Example
Next, create a runner file named BaseTests.java
BaseTest.java file
package features;
import com.intuit.karate.junit5.Karate;
import net.minidev.json.JSONObject;
import org.junit.jupiter.api.BeforeAll;
import testrails.APIClient;
import testrails.APIException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class BaseTest {
private static APIClient client = null;
private static String runID = null;
#BeforeAll
public static void beforeClass() throws Exception {
String fileName = System.getProperty("karate.options");
//Login to API
client = new APIClient("Write Your host, for example
https://yourcompanyname.testrail.io/");
client.setUser("user.name#companyname.com");
client.setPassword("password");
//Create Test Run
Map data = new HashMap();
data.put("suite_id", "Write Your Project SuitId(Only number)");
data.put("name", "Api Test Run");
data.put("description", "Karate Architect Regression Running");
JSONObject c = (JSONObject) client.sendPost("add_run/" +
TESTRAİL_PROJECT_ID, data);
runID = c.getAsString("id");
}
//Send Scenario Result to Testrail
public static void sendScenarioResults(boolean failed, List<String> tags, String errorMessage) {
try {
Map data = new HashMap();
data.put("status_id", failed ? 5 : 1);
data.put("comment", errorMessage);
client.sendPost("add_result_for_case/" + runID + "/" + tags.get(0),
data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
}
#Karate.Test
Karate ExampleFeatureRun() {
return Karate.run("ExampleFeatureRun").relativeTo(getClass());
}
}

Please look at 'hooks' documented here: https://github.com/intuit/karate#hooks
And there is an example with code over here: https://github.com/intuit/karate/blob/master/karate-demo/src/test/java/demo/hooks/hooks.feature
I'm sorry I can't help you with how to push data to testrail, but it may be as simple as an HTTP request. And guess what Karate is famous for :)
Note that values of tags can be accessed within a test, here is the doc for karate.tagValues (with link to example): https://github.com/intuit/karate#the-karate-object
Note that you need to be on the 0.7.0 version, right now 0.7.0.RC8 is available.
Edit - also see: https://stackoverflow.com/a/54527955/143475

Related

How to add RequestInterceptor and change Referer in BrowserMob-Proxy 2.0

I am using BrowserMob-Proxy inside a Selenium test suite. I would like to change the Referer for a few tests. I have added requestInterceptor from the 2.0 docs into our MyProxy class and while it does not generate an error the Referer is not changed.
For now, I am trying to get the requestInterceptor to work in the MyProxy class where the proxy is created. In the end, I would like to be able to specify the Referer in each test.
If anyone has suggestions on getting the requestInterceptor to work please let me know. Here is the MyProxy class. Please let me know if other code examples would be helpful to troubleshoot this.
import org.openqa.selenium.Proxy;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.proxy.ProxyServer;
import net.lightbody.bmp.proxy.http.BrowserMobHttpRequest;
import net.lightbody.bmp.proxy.http.RequestInterceptor;
public class MyProxy {
private ProxyServer proxy;
private boolean initialized;
public Har endCapture() throws Exception {
Thread.sleep(15000);
return this.proxy.getHar();
}
public Proxy getSeleniumProxy() {
return this.proxy.seleniumProxy();
}
public boolean isInitialized() throws Exception {
return this.initialized;
}
public void start() throws Exception {
int proxyPort = Integer.parseInt(System.getProperty("proxyPort"));
this.proxy = new ProxyServer(proxyPort);
this.proxy.start();
this.proxy.setCaptureHeaders(true);
this.proxy.setCaptureContent(true);
this.proxy.addRequestInterceptor(new RequestInterceptor() {
#Override
public void process(BrowserMobHttpRequest request, Har har) {
request.getMethod().removeHeaders("Referer");
request.getMethod().addHeader("Referer", "http://www.google.com");
}
});
this.initialized = true;
}
public void startCapture() throws Exception{
this.proxy.newHar("MyHar");
}
public void stop() throws Exception {
this.proxy.stop();
this.initialized = false;
}
}
I think the key here is how to test the newly-added header, which is tricky to do manually.
I chose as a test-site: http://headers.cloxy.net/request.php, which simply logs the names and values of all request headers. Having first set up my proxy, I arranged a screenshot to be written after page request completed.
I was able to determine that:
#Override
public void process(BrowserMobHttpRequest req, Har har) {
req.getMethod().removeHeaders("Referer");
req.getMethod().addHeader("Referer", "http://www.google.xyz");
// Some extras
req.getMethod().addHeader("Foo_" + System.currentTimeMillis(), "Bar_" + new java.util.Date());
req.getMethod().setHeader("Lorem_" + System.currentTimeMillis(), "Ipsum_" + new java.util.Date());
}
... successfully adds all the specified headers in both BrowserMob 2.0.0 and 2.1 beta 5. I've confirmed this for each version in Firefox (45), Chrome (49), and PhantomJS.
So, in short:
The OP's header-adding syntax is perfectly fine.
setHeader also works as expected.
BMP version numbers do not affect this (but by all means upgrade to 2.1 as/when it is released)
Browsers do not affect this
Review this issue and see if it describes your problem.
Suggestion is to move to the latest version of BrowserMobProxy which is 2.1.0-beta-5.

Cucumber: Unable to find step definition

I have the following feature file: MacroValidation.feature
#macroFilter
Feature: Separating out errors and warnings
Scenario: No errors or warnings when separating out error list
Given I have 0 macros
When I filter out errors and warnings for Macros
Then I need to have 0 errors
And I need to have 0 warnings
My definition files.
package com.test.definition;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumber.runtime.java.StepDefAnnotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
#StepDefAnnotation
public class MacroValidationStepDefinitions {
private final MacroService macroService = spy(new MacroService());
private final LLRBusList busList = mock(LLRBusList.class);
private final List<String> errorList = new ArrayList<String>();
private final List<String> warningList = new ArrayList<String>();
#Before({"#macroFilter"})
public void setUp() {
errorList.addAll(Arrays.asList("error 1, error2, error 3"));
warningList.addAll(Arrays.asList("warning 1, warning 2, warning 3"));
}
#After({"#macroFilter"})
public void tearDown() {
errorList.clear();
warningList.clear();
}
#Given("^I have (\\d+) macros$")
public void i_have_macros(int input) {
doReturn(input).when(busList).size();
}
#When("^I filtered out errors and warnings for Macros$")
public void i_filtered_out_errors_and_warnings_for_Macros() {
macroService.separateErrorsAndWarning(busList, errorList, warningList);
}
#Then("^I need to have (\\d+) errors$")
public void i_need_to_have_errors(int numOfError) {
if (numOfError == 0) {
assertTrue(errorList.isEmpty());
} else {
assertEquals(errorList.size(), numOfError);
}
}
#Then("^I need to have (\\d+) warnings$")
public void i_need_to_have_warnings(int numOfWarnings) {
if (numOfWarnings == 0) {
assertTrue(warningList.isEmpty());
} else {
assertEquals(warningList.size(), numOfWarnings);
}
}
}
My unit test class.
#CucumberOptions(features = {"classpath:testfiles/MacroValidation.feature"},
glue = {"com.macro.definition"},
dryRun = false,
monochrome = true,
tags = "#macroFilter"
)
#RunWith(Cucumber.class)
public class PageMacroValidationTest {
}
When I execute the test, I get file definition not implemented warnings in the log.
Example log:
You can implement missing steps with the snippets below:
#Given("^I have (\\d+) macros$")
public void i_have_macros(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I filter out errors and warnings for Macros$")
public void i_filter_out_errors_and_warnings_for_Macros() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I need to have (\\d+) errors$")
public void i_need_to_have_errors(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I need to have (\\d+) warnings$")
public void i_need_to_have_warnings(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I don't think file name should matter right?
It looks like Cucumber isn't finding your step defintion class. In your unit test class you say:
glue = {"com.macro.definition"}
However the step definition classes are in com.test.definition
Try changing that line to:
glue = {"com.test.definition"}
You may have to rebuild your project to pick up the change.
Also, Cucumber is sensitive to white space. If you try to make your runner or feature file pretty after having captured the snippets, you will get this problem.
Here's an example that drove me nuts for several hours while creating my first BDD. I had created the feature file and a skeleton runner which I ran and and captured the snippets. Then I prettified the feature file, and when I ran the runner got the errors.
Of course everything looked fine to my human brain, so the next few hours were spent in fruitless research here, and checking versions and bug lists. Finally I decided to compare the first two lines of the snippet to see what was different:
// #Then("^the test result is = \"([^\"]*)\"$")
// public void theTestResultIs(String ruleResult) throws Throwable {
#Then("^the test result is = \"([^\"]*)\"$")
public void theTestResultIs(String arg1) throws Throwable {
Doh!
Try to use all dependencies in POM.xml with io.cucumber group id which is the latest jars instead of info.cukes. After removing jars update the project with new imports and run the project.
Remember you have to replace all dependencies of info.cukes with io.cucumber

JUnit reporter does not show detailed report for each step in JBehave

I'm trying to set up JBehave for testing web services.
Template story is running well, but I can see in JUnit Panel only Acceptance suite class execution result. What I want is to see execution result for each story in suite and for each step in story like it is shown in simple JUnit tests or in Thucydides framework.
Here is my acceptance suite class: so maybe I Haven't configured something, or either I have to notate my step methods some other way, but I didn't find an answer yet.
package ***.qa_webservices_testing.jbehave;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.jbehave.core.Embeddable;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.parsers.RegexPrefixCapturingPatternParser;
import org.jbehave.core.reporters.CrossReference;
import org.jbehave.core.reporters.Format;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.ParameterConverters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ***.qa_webservices_testing.jbehave.steps.actions.TestAction;
/**
* suite class.
*/
public class AcceptanceTestSuite extends JUnitStories {
private static final String CTC_STORIES_PATTERN = "ctc.stories";
private static final String STORY_BASE = "src/test/resources";
private static final String DEFAULT_STORY_NAME = "stories/**/*.story";
private static final Logger LOGGER = LoggerFactory.getLogger(AcceptanceTestSuite.class);
private final CrossReference xref = new CrossReference();
public AcceptanceTestSuite() {
configuredEmbedder()
.embedderControls()
.doGenerateViewAfterStories(true)
.doIgnoreFailureInStories(false)
.doIgnoreFailureInView(true)
.doVerboseFailures(true)
.useThreads(2)
.useStoryTimeoutInSecs(60);
}
#Override
public Configuration configuration() {
Class<? extends Embeddable> embeddableClass = this.getClass();
Properties viewResources = new Properties();
viewResources.put("decorateNonHtml", "true");
viewResources.put("reports", "ftl/jbehave-reports-with-totals.ftl");
// Start from default ParameterConverters instance
ParameterConverters parameterConverters = new ParameterConverters();
return new MostUsefulConfiguration()
.useStoryLoader(new LoadFromClasspath(embeddableClass))
.useStoryReporterBuilder(new StoryReporterBuilder()
.withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
.withDefaultFormats()
.withViewResources(viewResources)
.withFormats(Format.CONSOLE, Format.TXT, Format.HTML_TEMPLATE, Format.XML_TEMPLATE)
.withFailureTrace(true)
.withFailureTraceCompression(false)
.withMultiThreading(false)
.withCrossReference(xref))
.useParameterConverters(parameterConverters)
// use '%' instead of '$' to identify parameters
.useStepPatternParser(new RegexPrefixCapturingPatternParser(
"%"))
.useStepMonitor(xref.getStepMonitor());
}
#Override
protected List<String> storyPaths() {
String storiesPattern = System.getProperty(CTC_STORIES_PATTERN);
if (storiesPattern == null) {
storiesPattern = DEFAULT_STORY_NAME;
} else {
storiesPattern = "**/" + storiesPattern;
}
LOGGER.info("will search stories by pattern {}", storiesPattern);
List<String> result = new StoryFinder().findPaths(STORY_BASE, Arrays.asList(storiesPattern), Arrays.asList(""));
for (String item : result) {
LOGGER.info("story to be used: {}", item);
}
return result;
}
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new TestAction());
}
}
my test methods look like:
Customer customer = new cutomer();
#Given ("I have Access to Server")
public void givenIHaveAccesToServer() {
customer.haveAccesToServer();
}
So they are notated only by JBehave notations.
The result returned in Junit panel is only like here (I yet have no rights to post images):
You should try this open source library:
https://github.com/codecentric/jbehave-junit-runner
It does exactly what you ask for :)
Yes, the codecentric runner works very nicely.
https://github.com/codecentric/jbehave-junit-runner

Play 2 framework testing simulate session and POST?

When running a web test like this
#Test
public void runInBrowser() {
running(testServer(3333), HtmlUnitDriver.class, new Callback<TestBrowser>() {
public void invoke(TestBrowser browser) {
browser.goTo("http://localhost:3333");
assertThat(browser.$("#title").getTexts().get(0)).isEqualTo("Hello Guest");
browser.$("a").click();
assertThat(browser.url()).isEqualTo("http://localhost:3333/Coco");
assertThat(browser.$("#title", 0).getText()).isEqualTo("Hello Coco");
}
});
}
How can one pass sessions values while using this kind of testing and how can one simulate a POST? Thanks :-)
These are Selenium tests with FluentLenium. Since you test with a browser you must use an HTML form with method POST to make a POST request.
browser.goTo("http://localhost:3333" + routes.Login.login().url());//example for reverse route, alternatively use something like "http://localhost:3333/login"
browser.fill("#password").with("secret");
browser.fill("#username").with("aUsername");
browser.submit("#signin");//trigger submit button on the form
//after finished request: http://www.playframework.org/documentation/api/2.0.4/java/play/test/TestBrowser.html
browser.getCookies(); //read only cookies
Maybe you don't want to make test with a browser but instead with HTTP you can use FakeRequests:
import static controllers.routes.ref.Application;
import static org.fest.assertions.Assertions.assertThat;
import static play.mvc.Http.Status.OK;
import static play.mvc.Http.Status.UNAUTHORIZED;
import static play.test.Helpers.*;
import play.libs.WS;
import java.util.HashMap;
import java.util.Map;
import org.junit.BeforeClass;
import org.junit.Test;
import play.mvc.Result;
import play.test.FakeRequest;
public class SoTest {
#Test
public void testInServer() {
running(testServer(3333), new Runnable() {
public void run() {
Fixtures.loadAll();//you may have to fill your database you have to program this yourself
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("userName", "aUsername");
parameters.put("password", "secret");
FakeRequest fakeRequest = new FakeRequest().withSession("key", "value").withCookies(name, value, maxAge, path, domain, secure, httpOnly).withFormUrlEncodedBody(parameters);
Result result = callAction(Application.signIn(), fakeRequest);
int responseCode = status(result);
assertThat(responseCode).isEqualTo(OK);
}
});
}
}
Also check out this answer: How to manipulate Session, Request and Response for test in play2.0

How to create a custom aggregator in Mule?

What is the recommended way to create a completely custom aggregator in mule 3.x? By completely custom, I mean according to my own logic, not using correlation IDs, message counts, etc.
The documentation on the mulesoft site is outdated, saying to use AbstractEventAggregator which does not exist in 3.x:
http://www.mulesoft.org/documentation/display/MULE3USER/Message+Splitting+and+Aggregatio
Digging deeper, it looks like this class has been renamed to AbstractAggregator in 3.x:
http://www.mulesoft.org/docs/site/3.2.0/apidocs/org/mule/routing/AbstractAggregator.html
However, there are no examples that show how to use this. The LoanBroker example described in the first link above actually uses a correlation aggregator (in the 2.x examples, which I assume is what the document is referring to).
At one point, there was an abstract class that had abstract methods shouldAggregate and doAggregate. This is the kind of class I would like to extend.
Look at TestAggregator below for an example of subclassing AbstractAggregator.
import org.mule.DefaultMuleEvent;
import org.mule.DefaultMuleMessage;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.store.ObjectStoreException;
import org.mule.api.transformer.TransformerException;
import org.mule.routing.AbstractAggregator;
import org.mule.routing.AggregationException;
import org.mule.routing.EventGroup;
import org.mule.routing.correlation.CollectionCorrelatorCallback;
import org.mule.routing.correlation.EventCorrelatorCallback;
import org.mule.util.concurrent.ThreadNameHelper;
import java.util.Iterator;
public class TestAggregator extends AbstractAggregator
{
#Override
protected EventCorrelatorCallback getCorrelatorCallback(MuleContext muleContext)
{
return new CollectionCorrelatorCallback(muleContext,false,storePrefix)
{
#Override
public MuleEvent aggregateEvents(EventGroup events) throws AggregationException
{
StringBuffer buffer = new StringBuffer(128);
try
{
for (Iterator<MuleEvent> iterator = events.iterator(); iterator.hasNext();)
{
MuleEvent event = iterator.next();
try
{
buffer.append(event.transformMessageToString());
}
catch (TransformerException e)
{
throw new AggregationException(events, null, e);
}
}
}
catch (ObjectStoreException e)
{
throw new AggregationException(events,null,e);
}
logger.debug("event payload is: " + buffer.toString());
return new DefaultMuleEvent(new DefaultMuleMessage(buffer.toString(), muleContext), events.getMessageCollectionEvent());
}
};
}
}