Karate UI: Can a separate file having a scenario written in plain English be mapped to Karate feature file [duplicate] - karate

How do I define my own StepActions class in a Karate test?
All I need is one working example (apparently nobody has an example of this anywhere; I looked and couldn't find anything and so I am asking here).
For example, how would I implement this helper step action in Java? In this case, how do I get access to the WebDriver driver instance from within Java context? Then, how do I call the embed?
#Slf4j
public class SeleniumStepActions extends StepActions {
public SeleniumStepActions(FeatureContext featureContext, CallContext callContext, Scenario scenario, LogAppender appender) {
super(featureContext, callContext, scenario, appender);
}
#When("^screenshot$")
public void takeAScreenShot()
{
// goals is to simulate this in a karate js test
// * def bytes = driver.screenshot()
// * karate.embed(bytes, 'image/png')
log.info("Testing my own custom action.");
}
}
It is possible the above won't work. I am just looking to be pointed in the right direction by someone who knows. I wish there was such an example in the karate demo.

You can't. Which is why there ain't any demo :P
For a detailed discussion, please read this thread: https://github.com/intuit/karate/issues/398
The summary:
Karate does not support the "Step Definitions" that Cucumber does
There are 2 ways to inject custom logic, a) JS, b) Java interop
These are more than sufficient to implement something close to custom "keywords" - see this example: https://twitter.com/KarateDSL/status/1128170638223364097
and another: https://twitter.com/KarateDSL/status/1144458169822806016
If you insist on making your test read like "plain english" (which IMHO is not worth it) - then Karate may not be the best choice for your team.

Related

Can i have my own given when then implementation in Karate for my own keywords? [duplicate]

How do I define my own StepActions class in a Karate test?
All I need is one working example (apparently nobody has an example of this anywhere; I looked and couldn't find anything and so I am asking here).
For example, how would I implement this helper step action in Java? In this case, how do I get access to the WebDriver driver instance from within Java context? Then, how do I call the embed?
#Slf4j
public class SeleniumStepActions extends StepActions {
public SeleniumStepActions(FeatureContext featureContext, CallContext callContext, Scenario scenario, LogAppender appender) {
super(featureContext, callContext, scenario, appender);
}
#When("^screenshot$")
public void takeAScreenShot()
{
// goals is to simulate this in a karate js test
// * def bytes = driver.screenshot()
// * karate.embed(bytes, 'image/png')
log.info("Testing my own custom action.");
}
}
It is possible the above won't work. I am just looking to be pointed in the right direction by someone who knows. I wish there was such an example in the karate demo.
You can't. Which is why there ain't any demo :P
For a detailed discussion, please read this thread: https://github.com/intuit/karate/issues/398
The summary:
Karate does not support the "Step Definitions" that Cucumber does
There are 2 ways to inject custom logic, a) JS, b) Java interop
These are more than sufficient to implement something close to custom "keywords" - see this example: https://twitter.com/KarateDSL/status/1128170638223364097
and another: https://twitter.com/KarateDSL/status/1144458169822806016
If you insist on making your test read like "plain english" (which IMHO is not worth it) - then Karate may not be the best choice for your team.

What is a Selenium wrapper?

Does it wrap around Selenium and provide a simpler or different method of invoking the functionality of Selenium?
I looked it up on Google and the best information I could find was this one https://www.ontestautomation.com/using-wrapper-methods-for-better-error-handling-in-selenium/.
This doesn't explicitly explain what a Selenium wrapper is but gives enough information to help understand what it is.
One of the definitions of a "wrapper" is:
In the context of software engineering, a wrapper is defined as an entity that encapsulates and hides the underlying complexity of another entity by means of well-defined interfaces.
So, any custom code you might use that implements Selenium code could be understood as a wrapper.
For example, Katalon Studio is a testing tool that uses Selenium under the hood i.e. Katalon's WebUI class methods are a wrapper around Selenium methods. The following two pieces of code are equivalent - they do the same thing:
Selenium (and Java)
WebElement element = driver.findElement(By.cssSelector("css-selector-of-the-element"));
element.click();
Katalon
WebUI.click(testObject) //testObject defined elsewhere
This is just a simple example, but it shows how can you hide complexity behind simpler commands.
I know this question has already been answered but I can see it was never accepted as an answer. Now, the answer above explains exactly what a wrapper is : encapsulation. Which in itself means also that it hides the underlying complexity of another entity (Selenium classes in this case).
But let me elaborate and give you an actual example.
I've built a Framework around Selenium and made a nuget package out of it internal to my company. But this is one example on how to wrap Selenium By class. Using a delegate, you can simplify a lot of the calling methods :
private delegate void ValidationMethodDelegate(By locator, int timeout = ELEM_TIMEOUT);
//This method actions a delegate for regularly used methods with a By locator parameter,
//the value of the selector and the selector type which is a built-in framework enum
private void ActionMethod(ValidationMethodDelegate delegateMethod, string selectorValue, SelectorType selectorType)
{
if (!string.IsNullOrWhiteSpace(selectorValue))
{
switch (selectorType)
{
case SelectorType.Id:
delegateMethod(By.Id(selectorValue));
break;
case SelectorType.Xpath:
delegateMethod(By.XPath(selectorValue));
break;
case SelectorType.TagName:
delegateMethod(By.TagName(selectorValue));
break;
case SelectorType.CssSelector:
delegateMethod(By.CssSelector(selectorValue));
break;
case SelectorType.ClassName:
delegateMethod(By.ClassName(selectorValue));
break;
case SelectorType.LinkText:
delegateMethod(By.LinkText(selectorValue));
break;
case SelectorType.PartialLinkText:
delegateMethod(By.PartialLinkText(selectorValue));
break;
default:
break;
}
}
else
{
throw new AssertionException($"{this.GetType().Name}::{MethodBase.GetCurrentMethod().Name}():: Selector Value : '{selectorValue}' cannot be null or empty.");
}
}
//Example on how the delegate is used
public void Click(string selectorValue, SelectorType selectorType)
{
ActionMethod(PageHelper.Click, selectorValue, selectorType);
}
The PageHelper is a static class that implements internally to the framework most of Selenium's methods with assertions and waiting implementations. I have several layers of complexity in my framework. But you can make it simple too. The method click for me is wrapped also in another class that implements two methods one that finds the element by and the other than waits for an element to appear on screen. Both are other wrappers around Selenium methods and assertions.
If you are only doing tests for one application and won't have further use of Selenium then a framework is not a solution for you. Also wrappers would be kind of redundant outside your test solution.
I would say that wrappers would only be useful in the context where you are making multiple use for it (like the click or find element, etc.)
"Wrapper" is more like a software development design pattern, which developers use in the codebase when it is necessary.
You can read more in the book:
https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_2?dchild=1&keywords=software+development+patterns&qid=1605187094&sr=8-2
In scope of automated testing, there are other terms. I will explain for mobile automation.
Driver (Espresso, UIAutomator, Robotium, XCUITest) - receive commands from test and send them to app specialized interface in understandable way
You sent a command to press a button to the GUI driver - it accepts it via API and sends to the app (and we see a tap on the button in GUI).
Another app (which is over driver, let's call it superstructure in this context) that interacts with the app under test via one or more drivers (increasing usability or increasing possibilities) like Appium, Calabash.
Frameworks (JUnit, TestNG, Cucumber) - app that allows us to prepare, launch and gather all info regarding test executions
It will look like this:
Framework -> Our tests -> Superstructure -> Driver -> GUI in our application

how to execute Cucumber Step defination with TestNG annotation

I am supposed to migrate on Cucumber. I do have project framework with Selenium, TestNG with Data Driven Framework, Maven. I am exploring Cucumber feasibility with TestNG annotation.
My question is, How we can create connection between #Test method and Step definition of cucumber. Let's example our code is written in #BeforeClass, #Test, #AfterClass method. So how we can migrate with Step definition.
Feature File :
Feature: Is it Friday yet?
Everybody wants to know when it's Friday
Scenario: Sunday isn't Friday
Given today is Sunday
When I ask whether it's Friday yet
Step Definition:
#Given("^today is Sunday$")
public void today_is_Sunday() {
// Write code here that turns the phrase above into concrete actions
System.out.println("this is demo1");
}
#When("^I ask whether it's Friday yet$")
public void i_ask_whether_is_s_Friday_yet() {
// Write code here that turns the phrase above into concrete actions
System.out.println("this is demo2");
}
Class Exection:
#CucumberOptions(features = "cfeature/firstDemo.feature", glue = { "mytest/Stepd" })
public class demo01 extends AbstractTestNGCucumberTests {
private TestNGCucumberRunner tcr;
#BeforeClass(alwaysRun = true)
public void beforeClass() throws Exception {
tcr = new TestNGCucumberRunner(this.getClass());
}
#Test(groups="cucumber", description="Runs CucumberFeature")
public void testdemo() {
System.out.println("Hello");
}
#AfterClass(alwaysRun = true)
public void afterClass() {
tcr.finish();
}
}
Console:
Hello
[33mUndefined scenarios:[0m
[33mcfeature/firstDemo.feature:4 [0m# Sunday isn't Friday
1 Scenarios ([33m1 undefined[0m)
5 Steps ([33m5 undefined[0m)
0m0.073s
You can implement missing steps with the snippets below:
As of now, #Test annotation is calling. But, How to replace it with Step Definition. Please assist.
Not sure what the confusion here. Here's how you can relate TestNG and cucumber terminologies.
<test> tag in TestNG can be visualized as a feature file in cucumber.
#Test method in TestNG can be visualized as a scenario in cucumber.
A Step definition in cucumber has nothing directly equivalent to in TestNG because, its part of a scenario. But for the sake of understanding you can visualize it as one line of code doing a logical operation in TestNG.
The default implementation of AbstractTestNGCucumberTests is as below:
It contains a data provider internally which provides one feature file at a time.
It contains a #Test method which is bound to the above mentioned data provider, which retrieves all the scenarios in the feature file and then runs them one after the other.
You can build your own variant of AbstractTestNGCucumberTests to do various different things (such as support concurrent scenario execution which is currently not available in Cucumber JVM bindings).
As an example you can take a look at Cucumber-roadrunner library that I built which uses the above concept to support parallel scenario execution and also provides thread safe reports.
With respect to the error you are facing viz., You can implement missing steps with the snippets below: is basically because cucumber jvm bindings perhaps isn't able to bind your feature file with a glue code (which is what you are providing via the #CucumberOptions annotation). You should perhaps take a closer look at the cucumber jvm bindings documentation to understand how to provide the correct values.
You can also take a look to gherkin with QAF which is pure TestNG implementation for gherkin. It is using TestNG (NOT cucumber runner) and provides you all the features of testNG including parallel execution, listeners, grouping, priority etc...
Each scenario converted as TestNG test and you can run scenarios as parallel. Furthermore you can also use inbuilt or custom data-providers while authoring BDD. No need additional runner just configure as usual using appropriate factory class for the BDD syntax you are using.

Mule- Behaviour-Driven Development using JBehave

Is it possible to use JBehave for BDD testing in mule application? Any working example will be very helpful.
Thank you :)
should be possible. What do you want to test? It's easy to test a single Java Transformer with JBehave, but it's getting worse when you start writing integration tests with JBehave. Seriously I won't do that.
It could work if you use MUnit with Java, but I would never ever mix Java JBehave stuff with XML MUnit tests because it will become unmaintainable.
I always test without a BDD tool as wrapper and use simple Given-When-Then-like syntax as names of my tests. For example: "should-be-irrelevant-when-purchaser-is-zero" is a name of one of my test. By using this you always see which test fails why.
looking forward to your response
In case you want to test a custom Java transformer like this one:
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractTransformer;
public class MyCustomTransformer extends AbstractTransformer {
#Override
protected Object doTransform(Object src, String enc) throws TransformerException {
return null;
}
}
It's definitely possible, but I don't see why it should be a benefit. I would use Mockito with Given/When/Then syntax instead.

Test driven development: Void methods

I have been learning about TDD (using JUnit) and I have a doubt about how to go about testing void methods, in which case I can't directly use something like an assertTrue() on the return value of a method.. For example, say I have a simple console based application, and a part of it prints a menu on screen, say using this method:
public void printMenu()
{
System.out.println("Menu:");
System.out.println("1. Option ONE");
System.out.println("2. Option TWO");
System.out.println("3. Exit");
}
My question is, do I actually have to test this method?? And if so, how should I do it?
It is difficult to unit test a method which relies on static method calls. It is not a matter of returning something or void. What you could do is abstract the printing into an interface and have your class depend on this interface (using constructor injection for example):
private SomePrinterInterface _printer;
public void printMenu()
{
_printer.println("Menu:");
_printer.println("1. Option ONE");
_printer.println("2. Option TWO");
_printer.println("3. Exit");
}
In your unit test you could mock the interface and verify if correct methods have been called on it. This way you could test the printMenu in independently.
First: testing UI is hard. Some people don't bother testing things like this because it is very difficult to write meaningful tests that aren't fragile to the point of uselessness. I wouldn't bother testing this method.
But:
If you want to test menu generation, because your menu code is complex and you need ways to ensure that it works, you have a couple choices.
Refactor your method so that it accepts the output stream as a parameter, then pass in an output stream whose contents you can inspect. You might also be able to redirect System.out to achieve this.
Refactor your method so that the menu is generated as a bunch of objects, then printed separately. You can inspect and verify those objects.
capture the console output and compare to expectations
You can not unit test this method.
This method does no logic or processing that you need to unit test.
If you need to unit test the Print Menu, you can consider outputing the result to a text file.
Then read the text file and compare the menu texts..