Logging Messages from Java Class back to the Karate Report - karate

We have a scenario where we have to post a json request and then validate few actions in the UI. So we have a karate feature file which hits a request and after that we are invoking a java class from within the feature file. The java class would run the Selenium Webdriver test of us. In the java methods we have few Assertions/Info Messages which we would like to log back to the Karate Reports.
Is there a way in Karate with which we can write these messages from my Java Class to the Karate Test Reports?

If you use the Karate parallel runner it is designed to collect anything logged to package com.intuit.karate, which will then appear in the cucumber-html-report.
So you can try using the same slf4j Logger - and it might work.
A better way might be to just return a Map back to Karate from your Java code, with all the information you need to log. Then all you need to do is use the print keyword. I would recommend this approach actually, it should be less complicated and it does not assume that you are using the Cucumber HTML reporting. You could even do Karate asserts with the match keyword on the JSON that you get, refer to this example: dogs.feature.

We did try logging back to “com.intuit.karate” as shown below and its logging to the ‘overview-features.html’ report
Logger in Java class :
private static final Logger logger = LoggerFactory.getLogger("com.intuit.karate");
However we made an observation that if an exception is thrown from the java class the exception would appear first and then followed by all the information that is logged, both looks to exist as a different piece in the report.
For e.g
This is sample method with logger in the java class which i am invoking from the feature file
public void myTestMethod() {
logger.info("Starting Test");
logger.info("Setting path of chrome driver");
System.setProperty("webdriver.chrome.driver", "chromedriver.exe"); //driver doesnt exist in this path
logger.info("invoking chrome"); // we would expect the exception to be thrown after this line
driver = new ChromeDriver();
logger.info("perform search in google");
driver.get("http://www.google.com");
driver.findElement(By.id("lst-ib")).sendKeys("Selenium");
driver.findElement(By.id("lst-ib")).submit();
driver.quit();
}
But in the reports the exception appears first and then all the information that is logged from the java class. Both looks like two different pieces in the report, please see the report here https://www.screencast.com/t/bBhAIj7WKj
In the above case would it be possible to have the exception thrown after the line where we log” invoking Chrome” i think this would make it easier to identify the test failures from the reports. Please let us know if this would be possible

It worked for me by passing the karate object from the javascript file to the java code. With this I was able to call the karate.log function from the Java code. This way I could see the messages on the report.

Related

Parsing Cucumber Feature Files into JSON or NDJSON using Java with Cucumber 7.6.0 or Gherkin-Java 24.0.0

Background of the Question:
Earlier Issue:
I have already asked this question in the past with attached thread below but the use case was different in that case. I just needed a way to print the JSON into stdout using (NodeJS) cucumber-js. I used Native Cucumber parsing using cucumber CLI commands as per (https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md).
How to convert cucumber gherkin feature files into JSON or AST format?
Current Issue:
I want to Parse Gherkin Feature Files to JSON using Java. These JSON files would be later interpreted and rendered into a front end dashboard where we could filter feature files based on tags, scenarios and text match for features.
I came through React cucumber (https://github.com/cucumber/react-components) Library but this is more of a JS Based solution and I need to process the Parsed Feature file JSON before passing to the view layer.
Can someone please provide the code snippet for parsing Gherkin Feature file to JSON in Java. I went through below threads but all are using deprecated code.
Cucumber feature file - parsing to an object
How to parse Cucumber feature file in java or groovy?
and a few more.
Please provide an example code snippet if possible. Thanks in Advance :)
You can use io.cucumber.junit.Cucumber for reference. Briefly in your case you would do the following:
public class Main {
public static void main(String[] args){
RuntimeOptions runtimeOptions = new CucumberPropertiesParser()
.parse(CucumberProperties.fromSystemProperties())
.addDefaultFeaturePathIfAbsent()
.build();
SynchronizedEventBus bus = synchronize(new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID));
FeatureParser parser = new FeatureParser(bus::generateId);
Supplier<ClassLoader> classLoader = ClassLoaders::getDefaultClassLoader;
FeaturePathFeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(classLoader, runtimeOptions,
parser);
List<Feature> features = featureSupplier.get();
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeWithDefaultPrettyPrinter().writeValueAsString(features));
}
}

Karate - How to add Junit RunListener to KarateParallel Runner

I am trying to add RunListener to Karate ParallelRunner class. I have done this for Karate runner using #Karate.class and add a custom runner. I am writing the data to infuxdb and generating reports is grafana, I am able to successfully achieve it in karate runner. Below is the code snippet for the same. I am running my karate runner using this custom runner where I have added this listener. I want to achieve the same for parallel runner.
#Override
public void run(RunNotifier notifier) {
notifier.addListener(new ExecutionListener());
super.run(notifier);
This is not directly possible, the parallel runner is a very specific implementation and has nothing to do with JUnit by design.
Since you seem to be experienced in adding JUnit listeners and the like, you can refer to this code in case it gives you any ideas.
CliExecutionHook.java.
For more details about the "ExecutionHook" refer this: https://github.com/intuit/karate/issues/970#issuecomment-557443551
But let me say I think you are un-necessary trying to put effort into reports that will not really get you any benefit in the long run except for "looking good" :) And if you feel something needs to change in Karate, please contribute, it is open-source.
Thanks for your suggestion peter. I was able to send scenario and test run details to influx db in order to generate reports in grafana. I just made use of karate results extracted all the values required and called it in Junit #After.
public void writeScenarioResults(List<ScenarioResult> results){
String status;
for (ScenarioResult a:results) {
status=((a.isFailed()==true)?"FAIL":"PASS");
gb.sendTestMethodStatus(a.getScenario().getName(),status,build);
}
}

I want to run each .feature file as single TestNG test using Karate?

I want to run each .feature file as single TestNG test using Karate, how can I do it?
We are using karate to automate REST API's. We have custom listener which will record status of each TestNG test and other information to postgress DB.
One more way running by tags:
#CucumberOptions(tags = { "#getVersion" })
public class GetVersionTest extends KarateRunner {
}
Feature File:
#getVersion
Feature: Testing Rest API with Karate and Java
Scenario:
Given url 'https://......'
When method get
Then status 200
And match response contains '{version= x.xx.x}'
Did you try using the Karate TestNG support ? The documentation has details on how to use: https://github.com/intuit/karate#running-with-testng
As the developer of Karate I actually strongly recommend that teams don't use TestNG. My suggestion is that you use the new 'hooks' feature to call your custom Java code from Karate directly and you won't depend on TestNG or even JUnit.
If you still need a custom way of running, the TestNG support is actually a single class: KarateRunner.java. I really don't know if it runs each feature as a TestNG test or not since I am not a TestNG expert. But you should be able to create your own version of this Java code that does what you want and maybe contribute it back to the project.

Selenium, questions about code re-factoring

With Selenium IDE I generate a sample script for test the log to a website and a value in the website after logging. So my script is (Java) :
#test
public void mytest() throws Exception{
// Load the home page
...
// complete the log form
...
// check if the log work
...
// Logged : click on some element in the page
...
// Logged ; check the information X (if one HTML element contains child or not
...
}
I use JUnit for run the test class from a main class. My question is : What is the best way for re-factoring my code ? I would like create one class by "step", is it possible ? by example :
Class for load page and check there isn't error 404
Class for complete the log form, submit and check if the user is logged
Class for navigate in the website and get the information I want
Is it the best way? There isn't a real goal. Just, I want know how organize the code for a maximum of reuse (sorry for my bad English x) )
There are couple of reasons why you do not want to use Selenium IDE, do the recording for the test cases and refactor the code afterwards. Most of the time selenium IDE will provide you the selectors that are not stable enough. For rerunning the tests you want to make sure the selectors are stable enough and will not possibly depend on html structure. Second, as the test suite getting larger you want to reduce the code duplication as much as possible. Using Selenium IDE there is no way to understand which code blocks can be reused.
So, bottom line is for a good test suite start building a framework from scratch instead of using Selenium IDE. There are a lot of example out there how to start. I have one with TestNG here if that helps.

How to use webdriver using the dart library?

I am having trouble getting started with the webdriver dart library.
I was hoping for some simple examples.
I do have the seleniumn server standalone running in the background.
I am very new to dart and very experienced with ruby and watir-webdriver.
I was expecting something similar to the code below
import 'package:webdriver/webdriver.dart';
main() {
var url = "http://google.com";
var driver = new WebDriver();
b = driver.newSession(browser:'firefox');
b.getUrl(url);
}
But the error I am getting is
Unhandled exception:
No constructor 'WebDriver' declared in class 'WebDriver'.
Looking at the source
class WebDriver extends WebDriverBase {
WebDriver(host, port, path) : super(host, port, path);
So it seems like the constructor is there; and the defaults are in the WebDriverBase to go to the remote server. What am I doing wrong? I have scoured the internet trying to find simple examples with no luck
Currently, there are known issues with local and session storage, script execution, and log access.
To use these bindings, the Selenium standalone server must be running. You can download it at http://code.google.com/p/selenium/downloads/list.
There are a number of commands that use ids to access page elements. These ids are not the HTML ids; they are opaque ids internal to WebDriver. To get the id for an element you would first need to do a search, get the results, and extract the WebDriver id from the returned Map using the 'ELEMENT' key. see http://commondatastorage.googleapis.com/dartlang-api-docs/13991/webdriver.html