Is it possible to include the same few lines of scenario at the beginning of a new one? - behat

I have a 138 tests long scenario that allows me to test if a workflow works as it should.
However, I'm not a huge fan of having to repeat the same 6 lines that allows me to log in as an administrator, which are:
Given I am on "user/login"
And I fill in "admin#admin.com" for "name"
And I fill in "admin" for "pass"
And I press "Log in"
Then I should get a "200" HTTP response
And I should see "Dashboard"
I repeat this part 6 times so far, and I'm planning on needing to add this a few more time for some other tests.
So my question is the following: is there a way, through the FeatureContext file or any other way, to make these lines repeat?
Thank you in advance
So this is how I did:
Instead of calling Gherkin sentence one after the other, I parsed the vendor/ directory to find examples of how sentences where made.
my function to that connects me looks like the following:
/**
* #throws ElementNotFoundException
* #throws Exception
* #Given I am the administrator
*/
public function iAmTheAdministrator(){
$this->visitPath('/user/login');
$element = $this->getSession()->getPage();
$element->fillField('name', 'admin#admin.com');
$element->fillField('pass', 'admin');
$element->pressButton("Se connecter");
$this->assertSession()->pageTextContains('Dashboard');
}
This is pretty straight forward, and works well

There are 2 ways I know of that repeats steps. One is with background steps and the other involves running snippets of steps.
Background steps run at the start of each scenario.
Background:
Given I have done this
And this other thing
Scenario: Do stuff
When I do this
Then stuff should happen
This only works if all tests have the same starting procedure...
Snippets run whenever you call them which I assume you would rather want
Given I have logged in as an administrator
Step definition:
Given(/^I have logged in as an administrator$/) do
steps %{
Given I am on "user/login"
And I fill in "admin#admin.com" for "name"
And I fill in "admin" for "pass"
And I press "Log in"
Then I should get a "200" HTTP response
And I should see "Dashboard"
}
end
This allows you to use only one step which you can call at any time to run multiple steps
Hope this helps.

Related

KARATE- How to pass response from one scenario to other scenario in same feature [duplicate]

Does Karate supports a feature where you can define a variable in a scenario and reuse it in other scenarios in the same feature file. I tried doing the same but get an error. What's the best way to reuse the variables within the same feature file ?
Scenario: Get the request Id
* url baseUrl
Given path 'eam'
When method get
Then status 200
And def reqId = response.teams[0]resourceRequestId
Scenario: Use the above generated Id
* url baseUrl
* print 'From the previous Scenario: ' + reqId
Error:
Caused by: javax.script.ScriptException: ReferenceError: "reqId" is not defined in <eval> at line number 1
Use a Background: section. Here is an example.
EDIT: the variable if in the Background: will be re-initialized for every scenario which is standard testing framework "set up" behavior. You can use hooks such as callonce - if you want the initialization to happen only once.
If you are trying to modify a variable in one scenario and expect it to be now having that modified value when the next Scenario starts, you have misunderstood the concept of a Scenario. Just combine your steps into one Scenario, because think about it: that is the "flow" you are trying to test.
Each Scenario should be able to run stand-alone. In the future the execution order of Scenario-s could even be random or run in parallel.
Another way to explain this is - if you comment out one Scenario other ones should continue to work.
Please don't think of the Scenario as a way to "document" the important parts of your test. You can always use comments (e.g. # foo bar). Some teams assume that each HTTP "end point" should live in a separate Scenario - but this is absolutely not recommended. Look at the Hello World example itself, it deliberately shows 2 calls, a POST and a GET !
You can easily re-use code using call so you should not be worrying about whether code-duplication will be an issue.
Also - it is fine to have some code duplication, if it makes the flow easier to read. See this answer for details - and also read this article by Google.
EDIT: if you would like to read another answer that answers a similar question: https://stackoverflow.com/a/59433600/143475

The value of the variable on the right hand side of an assignment has been updated after the left hand side variable's value changed afterwards [duplicate]

Does Karate supports a feature where you can define a variable in a scenario and reuse it in other scenarios in the same feature file. I tried doing the same but get an error. What's the best way to reuse the variables within the same feature file ?
Scenario: Get the request Id
* url baseUrl
Given path 'eam'
When method get
Then status 200
And def reqId = response.teams[0]resourceRequestId
Scenario: Use the above generated Id
* url baseUrl
* print 'From the previous Scenario: ' + reqId
Error:
Caused by: javax.script.ScriptException: ReferenceError: "reqId" is not defined in <eval> at line number 1
Use a Background: section. Here is an example.
EDIT: the variable if in the Background: will be re-initialized for every scenario which is standard testing framework "set up" behavior. You can use hooks such as callonce - if you want the initialization to happen only once.
If you are trying to modify a variable in one scenario and expect it to be now having that modified value when the next Scenario starts, you have misunderstood the concept of a Scenario. Just combine your steps into one Scenario, because think about it: that is the "flow" you are trying to test.
Each Scenario should be able to run stand-alone. In the future the execution order of Scenario-s could even be random or run in parallel.
Another way to explain this is - if you comment out one Scenario other ones should continue to work.
Please don't think of the Scenario as a way to "document" the important parts of your test. You can always use comments (e.g. # foo bar). Some teams assume that each HTTP "end point" should live in a separate Scenario - but this is absolutely not recommended. Look at the Hello World example itself, it deliberately shows 2 calls, a POST and a GET !
You can easily re-use code using call so you should not be worrying about whether code-duplication will be an issue.
Also - it is fine to have some code duplication, if it makes the flow easier to read. See this answer for details - and also read this article by Google.
EDIT: if you would like to read another answer that answers a similar question: https://stackoverflow.com/a/59433600/143475

Create JSON request body for POST API2 with one dynamic field which comes from API1 response [duplicate]

Does Karate supports a feature where you can define a variable in a scenario and reuse it in other scenarios in the same feature file. I tried doing the same but get an error. What's the best way to reuse the variables within the same feature file ?
Scenario: Get the request Id
* url baseUrl
Given path 'eam'
When method get
Then status 200
And def reqId = response.teams[0]resourceRequestId
Scenario: Use the above generated Id
* url baseUrl
* print 'From the previous Scenario: ' + reqId
Error:
Caused by: javax.script.ScriptException: ReferenceError: "reqId" is not defined in <eval> at line number 1
Use a Background: section. Here is an example.
EDIT: the variable if in the Background: will be re-initialized for every scenario which is standard testing framework "set up" behavior. You can use hooks such as callonce - if you want the initialization to happen only once.
If you are trying to modify a variable in one scenario and expect it to be now having that modified value when the next Scenario starts, you have misunderstood the concept of a Scenario. Just combine your steps into one Scenario, because think about it: that is the "flow" you are trying to test.
Each Scenario should be able to run stand-alone. In the future the execution order of Scenario-s could even be random or run in parallel.
Another way to explain this is - if you comment out one Scenario other ones should continue to work.
Please don't think of the Scenario as a way to "document" the important parts of your test. You can always use comments (e.g. # foo bar). Some teams assume that each HTTP "end point" should live in a separate Scenario - but this is absolutely not recommended. Look at the Hello World example itself, it deliberately shows 2 calls, a POST and a GET !
You can easily re-use code using call so you should not be worrying about whether code-duplication will be an issue.
Also - it is fine to have some code duplication, if it makes the flow easier to read. See this answer for details - and also read this article by Google.
EDIT: if you would like to read another answer that answers a similar question: https://stackoverflow.com/a/59433600/143475

What are the best practices for using waitFor{} and sleep() in geb automated testing?

Currently in the process of learning how to write automated tests using geb so this may be bit of a noob observation and question. Is it just me or when running many tests one after another seem to speed up the the execution of the tests? For example, when write a new test I'll comment out my other tests just to run a single method or two to make sure its working properly. Everything will run fine and pass. Then when I uncomment everything to run the full test, the test appears to run extremely fast and to the point where the web application I'm automating cant keep up and will cause my tests to fail due to elements not being loaded. Even when using waitFor{} blocks. i found that using sleep(1000) in certain places has helped but I feel as though there is probably a better way to approach this problem. The web application I'm working with seems to refresh the page a lot whenever the user does anything with a field which may be part of the problem that I don't really have control over. at one part in my test I need to fill out a form but the page refreshes after fill out out an input so I've written the code below that works but looks kind of meh because of all the sleep statements.
void populateRequiredFields(){
def fName = "Test"
def lName = "User"
def email = "abc#abc.com"
def question = "Do you even test bro?"
clear.click()
//sleep() to slow down test in order to get correct elements due to page refreshing
sleep(3000)
firstName << fName
sleep(1000)
lastName << lName
sleep(1000)
emailAddress << email
sleep(1000)
veryifyEmail << email
sleep(1000)
questionField << question
sleep(1000)
}
If you need to wait longer than the standard 10 seconds provided by waitFor, you can do this:
waitFor(30, 0.5){ firstName << fName }
This will wait for 30 seconds and check every half second.
I found that it's best to enclose logic that waits for the page to be in the expected state after a typically asynchronous action is performed inside of methods on page objects and modules. This way you don't litter your tests with all the waitFor {} noise and you won't forget to wait for things when you add more tests because waiting is part of the reusable logic.
So in your case:
import geb.Page
class APageThatCanBeCleared extends Page {
static content = {
clear { $(/*whatever the selector for the clearing element is*/) }
firstName { $(/*whatever the selector for the first name element is*/) }
}
void clear() {
clear.click()
waitFor { firstName.displayed }
}
}
and then in your test:
to APageThatCanBeCleared
clear()
firstName << "Test"
Using sleep() is not a good idea. Try to use waitFor {some results are present}

Maven an java.io.scanner(System.in)

I'm running into issues with my project. When running in Netbeans it seems to work fine with user interaction. However when I run using mvn test it does not. I see the command line menu but I am not prompted to make a selection. When I force terminate the project, I get an error about No Line Found.
Any Ideas? I'm stumped.
The line that isn't working is essentially:
System.out.print("1) Print String\n"
+ "0) Exit\n"
+ "Enter Selection: ");
String line = (new java.util.Scanner(System.in)).nextLine();
I see the output Similar to this:
1) Print String
0) Exit
But I don't see "Enter Selection: " and it doesn't prompt for the String input. I terminate and get "No Line Found" though after I cancel the execution I see the whole string int he "Test Results window".
It's abnormal for unit tests to pause for user interaction. I wouldn't be surprised if it acts strangely. I expect the testing libraries don't really anticipate this sort of thing.
In practice, one should not interact with user while performing JUnit tests. Tests should be designed to operate automatically and continuously. If you want to test underlying code with two separate values, two tests should be implemented and call each the underlying code with their own value. This should cover for the two options offered to your user.