Write jBehave example step - java

I want to write a jBehave step as follows;
#When("I perform <someAction> on $panel")
So I can have steps like
i. When I perform Action1 on Panel1
ii. When I perform Action2 on Panel2
Now as you can see, this step has a mix of placeholder
1. someAction which actually comes via meta
2. $panel which is taken from the step text in the story
But this is not working from me and I get NullPointerException
It works if I write
#When("I perform <someAction> on Panel1")
i.e. I cannot use the 2 placeholders in the same step.
But since this is a generic step, I do not want to hard code any values.

Yes you can
#When("I perform <someAction> on *panel*")
public void perform(#Named("panel") String panelId){
}
and from now, I recommend to identify all elements by name, using jemmy you can use a new NameComponentChooser(panelId)

Please use $symbol before both your parameters. Then both the example parameter as well as the normal parameter will be handled.
#When("I perform $action on $panel")
public void performAction(String action, String panel){
}

Related

Cucumber-JVM: Call a Scenario or ScenarioOutline inside a step definition

I have a step definition where I pass the name of a Scenario or Scenario outline:
#When("^I execute the steps of the following scenario or scenario outline: \"([^\"]*)\"$")
public void execute_steps_of_the_scenario_or_scenario_outline(String name){
...
}
My intent is to execute all the steps of the called Scenario/ScenarioOutline, and append those executed steps to the current scenario. This means that the steps of the called scenario become a part of the current scenarion.
However I have been unable to figure out a way to do this.
Cucumber (and BDD/TDD in general) are not meant to be used like that. Each scenario/test should be isolated from each other and is not a good practice to executes steps from one scenario on another.
You can use Background steps on a feature to execute common steps across the scenarios of that feature or you can also use tags to execute a particular set of actions before and/or after a scenario is executed using Hooks.
Having said that, you could write some logic in your glue code to maintain a list of steps (methods) which are invoked in each scenario and invoke the same list of steps on a subsequent scenario. This assumes that you could guarantee the execution order of the scenarios, which is (again) against all TDD best practices. Below is an example of the skeleton code to achieve what I have just described.
private Scenario scenario;
private Map<String, List<String>> scenarioSteps = new HashMap<>();
#Before
public void setUp(Scenario scenario) {
this.scenario = scenario;
scenarioSteps.put(scenario.getName(), new LinkedList<>());
}
#Given("^the first step is executed$")
public void the_first_step_is_executed() {
final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[1];
scenarioSteps.get(scenario.getName()).add(stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
}

Java Cucumber storing value returned by step

i'm writing a cucumber test and i come up with some difficulty:
I have a step which creates dto and saves it using save client which returns dto back again i would need to use that returned dto for other step but don't know how to make it.
Here's how it looks in code :
commonExpenseCreationSteps.java
#Given("^new \"([^\"]*)\" expense with type \"([^"]*)\"$")
public ExpenseDTO newExpense(String description, String expenseType) throws Throwable {
ExpenseDTO expenseDTO = new ExpenseDTO();
expenseDTO.setDefaultPurpose(description);
expenseDTO.setExpenseType(expenseType);
return expenseSaveClient.save(expenseDTO);
}
expenseTransactionsSendSteps.java
#Given("^send expense for Approval$")
public void sendExpenseForApproval() throws InterruptedException {
expenseTransactionSendClient.sendToApproval(expenseDTO);
}
How it would be possible to store value returned by one Step and use it in other one in this case i return ExpenseDTO in newExpense method but i need to use it in sendExpenseForApproval but don't know how to do it !?
Create expenseDTO object outside of your glue code, probably in your stepdef class constructor.
ExpenseDTO expenseDTO = new ExpenseDTO();
The way to share state between steps in the same class is to use instance variables. Set the value in one step and use that value in a later step.
The way to share state between steps with two or more step classes is to use dependency injection.
I wrote a blog post that describes how it can be done using PicoContainer.

How to cast a variable extracted from a payload in citrus framework?

I'm creating IT tests with Citrus Framework. I have two calls to the server, one for creating a user and another one for performing some operation with that user.
Problem: I need a value from the create user request that is not a String, to put it in the request of the second call. Extraction of the value:
new SoapActionBuilder()
.client(webServiceClient)
.receive()
.namespace("ns", MY_NAMESPACE)
.extractFromPayload("//ns:someId", "someId")
And then this someId has to be used for building the next request. If it was a String it would be:
request.setSomeId("${someId}");
But it is a Long, so doing the casting doesn't work (Citrus resolves that value later on, and Long#valueOf is executed in that very moment):
request.setSomeId(Long.valueOf("${someId}"));
Is there any way to easily cast that variable (maybe on extraction)?
I manage to do it with a JavaAction, but is very weird for using it regularly (3 lines and a new method are needed). It's something like:
public void test() {
...
action(new JavaActionBuilder(new JavaAction().setInstance(this))
.method("setSomeId")
.methodArgs(request, "${someId}"));
...
}
public void setSomeId(Request request, String someId) {
request.setSomeId(Long.valueOf(someId));
}
Best way to access test variable objects in a TestDesigner is to do so in a test action. The Citrus test designer has a design time where the complete test case is constructed. Later on at runtime the test is executed and your XPath expression is evaluated to the test variable. So you may add a new test action like this:
action(new AbstractTestAction() {
#Override
public void doExecute(TestContext context) {
Long someId = Long.valueOf(context.getVariable("someId"));
// do something with someId
}
}
In contrast to that you could use the Citrus TestRunner which does not have a separate design time. However you must access the Citrus TestContext in order to read the variable as long value.

How to test a the retrieve method of my class without testing the insert in the same testcase?

I am learning unit tests (in a TDD-like approach).
I am creating a class that encapsulates an collection, it has 3 methods:
store
retrieveAllDocuments
hasItem
I created one test: testRetrieveWhenEmpty, whici goes like this:
#Test
public void testRetrieveAllDocumentsWhenEmpty() {
List<String> storedDocs = state.retrieveAllDocs();
assertNotNull(storedDocs);
assertEquals(0, storedDocs.size());
}
And then I made it pass.
Now I would like to create a testRetrieveAllDocumentsWhenNotEmpty, which would be like this:
#Test
public void testRetrieveAllDocumentsWhenNotEmpty() {
state.store("test") //This is the only api point that I can use to insert things
List<String> storedDocs = state.retrieveAllDocs();
assertNotNull(storedDocs);
assertEquals(1, storedDocs.size());
assertEquals("test", storedDocs..get(0));
}
But now I have to implement the store method, so I created the following test method:
#Test
public void testStoreDocument() {
state.store("test")
List<String> storedDocs = state.retrieveAllDocs(); //This is the only api point I can use to see the content
assertNotNull(storedDocs);
assertEquals(1, storedDocs.size());
assertEquals("test", storedDocs.get(0));
}
I see two problems:
These methods are identical.
I test two methods in each test, if the store fails, I get a message that the retrieve has a problem.
Using reflection would bind my test to my implementation, and I am trying to avoid it.
Changing the interface for better testing is hard to argument to my team mates.
What approach do you take in these cases? (Is this case a problem at all?)
You could try shifting your view from writing "a (set of) tests per method" to "a test per useful behaviour" of the class you are testing.
If this class is both reader and writer of the data, it kinda makes sense to use its insert operations when testing the retrieval behaviour and vice versa.
I'd test the no items, one item, multiple items, has a specific item, does not have a specific item cases. These tests would implicitly test the store method as well.
Kevlin Henney's talk programming with GUTs provides a good explanation about this concept.
Actually does not need to be equals:
In testRetrieveAllDocumentsWhenNotEmpty you can add more than one document then check size, also you don't need to get all individual documents, you need to assert size is the correct.
This method asserts to get ALL documents in a non empty scenario, if you can assert you inserted 3, AND as long the testStoreDocument exists, you don't need to assert the document retrieve but yes the list size to know if ALL are returned.
#Test
public void testRetrieveAllDocumentsWhenNotEmpty() {
state.store("test1")
state.store("test2")
state.store("test3")
List<String> storedDocs = state.retrieveAllDocs();
assertNotNull(storedDocs);
assertEquals(3, storedDocs.size());
}
In testStoreDocument, you need to get the document, you don't need to assert the size of stored documents.
#Test
public void testStoreDocument() {
state.store("test")
List<String> storedDocs = state.retrieveAllDocs(); //This is the only api point I can use to see the content
assertNotNull(storedDocs);
assertEquals("test", storedDocs.get(0));
}
As mention before try to write your unit tests in a way they test scenarios. Every reader understands then better what you class is for. Since we do not just want to use a method, we want to achieve something with this method.
You can express this in the name of your tests like this: when{SomethingHappens}Then{ThisIsExpected} or given{Situation}Should{BeHandledInThisWay}
You could create tests like givenStoredDocumentsShouldBeAllReturned and whenDocumentIsStoredThenItCanBeRetrieved

jBehave write common step

Can I have the following step method using jBehave;
#When("I select action <actionText> on <panelTitle>")
#Alias("I select action $actionText on $panelTitle")
public void myMethod(#Named("actionText") String actionText, #Named("panelTitle") String panelTitle) {
// My code
}
So as you can see, the step text is the same. Only thing is in one case, the value is through
parameter injection and in other it is through parameterised scenarios
I have seen similar implementation in link:
http://jbehave.org/reference/stable/parametrised-scenarios.html
So, you can use this method.

Categories