I'm very new to BDD and cucumber testing. I have tried to combine BDD cucumber testing with Rest Assured and I'm facing some issues and need your help
I have a very simple feature file
Feature: End to end test for add category feature
Scenario Outline:Successful addition of a new category
When I try to add a category with request file <requestFile>
Then I receive HTTP status <status>
And The response matches response from file <responseFile>
Examples:
| requestFile | status | responseFile
| "json-files/category/requests/category.json" | 201 | "json-files/common/expected-responses/requestSuccessfullyProcessed.json"
| "json-files/category/requests/category-name-missing.json" | 400 | "json-files/category/expected-responses/category-name-missing.json"
My plan is very simple. I have a pair of a request and a response file and I'm performing end-to-end regression testing.
It's throwing an error in the last step where it's supposed to validate the response file saying step undefined. When I uncommented my step definition methods and tried to let cucumber generate the steps I noticed that this is what it is generating
Step undefined
You can implement this step and 2 other step(s) using the snippet(s) below:
#When("I try to add a category with request file {string}")
public void i_try_to_add_a_category_with_request_file(String string) {
// Write code here that turns the phrase above into concrete actions
throw new io.cucumber.java.PendingException();
}
#Then("I receive HTTP status {int}")
public void i_receive_http_status(Integer int1) {
// Write code here that turns the phrase above into concrete actions
throw new io.cucumber.java.PendingException();
}
#Then("The response matches response from file <responseFile>")
public void the_response_matches_response_from_file_response_file() {
// Write code here that turns the phrase above into concrete actions
throw new io.cucumber.java.PendingException();
}
Notice that the last method somehow didn't generate the {string} argument and this is the reason even when I define the steps, it's not working.
I have no clue if I have made any mistakes in the feature file. A bit of help would be great
Related
We have REST APIs with JSON BODY arrays/objects. To control the data to go in the JSON file at Runtime, using testdata.properties file where defining the data and calling that as below. We are using cucumber Serenity.
Testdata.properties file:
Value = 123
StepDefinition file:
#Given("^Set the \"([^\"]*)\" with \"([^\"]*)\"$")
public void set_data_parameterization (String fieldName, String Value) {
if (fieldName.contains("Test")) {
jsonObjectNew.getAsJsonObject("TestInfo").add("Value",
gson.toJsonTree(Value));
}
System.err.println("Test value fetched from the Scenario outline");
}
JSON File:
{
"TestInfo": {
"Test123": 3,
"Value": 50 // this value to be replaced
}
}
.feature file:
Scenario Outline::
1. Testing data parameterize
Given Set the URL for "Test" as "base"
And Set the "Test" with "Value"
Examples:
|Value|
|700|
|710|
If calling the variable data from .properties file works fine, however if want to have different sets of data to be executed for the same scenario. How can it be achieved. Tried with Examples in feature file, but when run the file as cucumbertest>getting the actual payload value which is 50. It is not replacing with 700/710.
Please guide.
Able to get values as expected now, the issue was I was trying as "String" (ex: "Values"). When tried as in .feature file and rest of the code is similar.
Able to get values iterated of given Examples.
I wrote my first Cucumber program today, and it fails. I wrote a very basic one, a simple scenario and it's step definition. Below is the feature file code and the step definition code.
Step Definiton code:
import cucumber.api.java.en.When;
import cucumber.api.java.en.Then;
public class Testing_Example1 {
#When("^I am on x page$")
public void i_am_on_x_page() throws Throwable {
System.out.println("I am on xPage");
}
#Then("^I see that element$")
public void i_see_that_element() throws Throwable {
System.out.println("I can see that page");
}
}
Feature File Code:
Feature: Testing
Scenario: s1
When I am on x page
Then I see that element
I have added the system variables as well - The JAVA_HOME and the maven variables as well and linked it to the PATH variable I system variables.
I have added dependencies in the POM file, such as the Cucumber-Java, Cucumber-Junit and for selenium as well and yet my program fails and says the steps are undefined.
Output:
1 Scenarios (1 undefined)
2 Steps (2 undefined)0m0.000s
You can implement missing steps with the snippets below:
#When("^I am on x page$")
public void i_am_on_x_page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I see that element$")
public void i_see_that_element() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
Undefined step: When I am on x page
Undefined step: Then I see that element
Process finished with exit code 0
I guess it's because my feature file is not getting linked with the step definition file, but I don't understand what is missing that the feature file does not execute properly and scenarios fail. Someone who has knowledge about this, do help.
Thank You!
I found the solution to this. I just edited the configuration of the feature file - > edit configurations -> Paste the path of the package in which your step definition file is present -> apply.
I just has to link the feature file to the step definition using Glue.
Specify the stepdefintion & feature file details in your cucumber runner class.
#CucumberOptions(
plugin={"pretty", "html:target/cucumber-html-report","json:target/cucumber-report.json"},
features = "src/test/resources",
glue ="com.vg.pw.ui.stepdefinitions",
)
public class CucumberRunner {
...
}
How does the code within the 'shouldFail?' block work? I understand that it is a closure, but the code gets called regardless of whether or not I call is using its signature. Besides, what's the deal with the "ReadOnlyPropertyException" showing up in the parenthesis? If it is a parameter, then it is not setup as listed in the official documentation!!
Questions: What is 'shouldFail'? How should it be invoked? How to handle the exception purportedly thrown by this method/function/closure?
void test02_ReadOnlyFieldInGroovyBean() {
// You've probably noticed how Groovy automatically generates getters/setters for you. But what if you don't
// want to generate a setter because it's a read-only field? Just mark it with 'final'. Groovy will understand.
// Try to modify Ken's ssn. You should get a ReadOnlyPropertyException.
def person = new GroovyPerson('Ken', 'Kousen', '7878')
def failed = false
shouldFail (ReadOnlyPropertyException) {
// ------------ START EDITING HERE ----------------------
System.out.println(" i am in should fail")
person.ssn='8332';
// ------------ STOP EDITING HERE ----------------------
failed = false
System.out.println(" exiting should fail")
}
//def foobar=shouldFail("hjh");
//def foobar=true;
failed=shouldFail('abc');
//System.out.println("Failed: "+failed);
assert failed
// The code wrapping your additions verifies that the ReadOnlyProperty exception has been thrown.
// The curly brackets ({}) represent a closure. We'll get into what that means very soon.
}
shouldFail() (in this variant) takes a class and a closure. It runs the closure and reports a test failure if the closure does NOT exit by throwing an exception of that type. As to catching the exception, you don't - shouldFail() does that for you.
See: http://docs.groovy-lang.org/latest/html/gapi/groovy/test/GroovyAssert.html#shouldFail%28java.lang.Class,%20groovy.lang.Closure%29
(Reading the comments and the code around them, it looks like this unit test should pass because setting the .ssn property of GroovyPerson will fail as it is a read-only property, causing a ReadOnlyPropertyException.)
I use the Cucumber framework, WebDriver and Java for auto testing. For parametrized tests I use table of parameters. And I don't know how to give whitespace as value of parameter. And I become to use keyword - WHITESPACE. My example bellow:
First method
Scenario Outline: checking of sending feedback
Given User wants send feedback
When User enters to the feedback field the following text:
"""
<suggestion>
"""
And User presses on the 'Send' button
Then User should see message <message>
Examples:
|suggestion|message|
|| Suggestion's field is empty!|
|\n| Suggestion's field is empty!|
|\n text text text| Successfuly send!|
|WHITESPACE| Successfuly send!|
then in step definition:
#When("^User enters to the feedback field the following text:$")
public void user_enters_feedback(String textOfSuggestion) {
textOfSuggestion.equals("WHITESPACE")?" ":textOfSuggestion;
new pageSuggestion().inpSuggestion.sendKeys(textOfSuggestion)
}
Second method for same scenatio
Also I try to use Transformer, but it did not work.
I created class
class MyTransformer extends Transformer<String> {
public String transform(String value) {
value.equals("WHITESPACE")?" ":value;
return value;
}
}
then in step definition:
#When("^User enters to the feedback field the following text:$")
public void user_enters_feedback(#Transform(MyTransformer.class) String textOfSuggestion) {
new pageSuggestion().inpSuggestion.sendKeys(textOfSuggestion)
}
How I can do it better for reusing with another steps or adding new keywords?
Thanks in advance.
You dont have to do anything at all. Consider this
Scenario Outline: Something
Given I have "<param>"
...
Examples:
|param|
| | #spaces
|| #empty
This happily prints "Empty..." when param is blank/empty
#Given("^I have \"(.*?)\"$")
public void i_have(String arg1) {
if (arg1.trim().equals("")) {
System.out.println("Empty...")
}
}
For a parameter class
class Criteria {
private Map params;
public getMap(){ return params; }
}
and a service method accept this criteria
class Service{
public List<Person> query(Criteria criteria){ ... }
}
A custom featureMatcher is used to match the criteria key
private Matcher<Criteria> hasCriteria(final String key, final Matcher<?> valueMatcher){
return new FeatureMatcher<Criteria, Object>((Matcher<? super Object>)valueMatcher, key, key){
#Override protected Object featureValueOf(Criteria actual){
return actual.getMap().get(key);
}
}
}
when using mockito to veryify the arguments:
verify(Service).query((Criteria) argThat("id", hasCriteria("id", equalTo(new Long(12)))));
The error message shows that:
Argument(s) are different! Wanted:
Service.query(
id <12L>
);
-> at app.TestTarget.test_id (TestTarget.java:134)
Actual invocation has different arguments:
Service.query(
app.Criteria#509f5011
);
If I use ArugmentCaptor,
ArgumentCaptor<Criteria> argument = ArgumentCaptor.forClass(Criteria.class);
verify(Service).query(argument.capture());
assertThat(argument.getValue(), hasCriteria("id", equalTo(new Long(12))));
The message is much better:
Expected: id <12L> but id was <2L>
How can I get such message, without using ArgumentCaptor?
The short answer is to adjust the Criteria code, if it's under your control, to write a better toString method. Otherwise, you may be better off using the ArgumentCaptor method.
Why is it hard to do without ArgumentCaptor? You know you're expecting one call, but Mockito was designed to handle it even if you have a dozen similar calls to evaluate. Even though you're using the same matcher implementation, with the same helpful describeMismatch implementation, assertThat inherently tries once to match where verify sees a mismatch and keeps trying to match any other call.
Consider this:
// in code:
dependency.call(true, false);
dependency.call(false, true);
dependency.call(false, false);
// in test:
verify(mockDependency).call(
argThat(is(equalTo(true))),
argThat(is(equalTo(true))));
Here, Mockito wouldn't know which of the calls was supposed to be call(true, true); any of the three might have been it. Instead, it only knows that there was a verification you were expecting that was never satisfied, and that one of three related calls might have been close. In your code with ArgumentCaptor, you can use your knowledge that there's only one call, and provide a more-sane error message; for Mockito, the best it can do is to output all the calls it DID receive, and without a helpful toString output for your Criteria, that's not very helpful at all.