I got a very basic question (new to Java) and which goes as below. To give a bit of background, I am using BDD driven test automation framework, working with CUCUMBER and JAVA.
I want to set a global variable in my main class object depending on the parameter/value in one of my step definitions and then access the same variable across the test in other step definitions (or objects)
Let's say my class is
public class FeatureStepDefinitions{
#Given("I want to login to system as (.+)$")
public void iWantToLoginToSystemAs(String userType)
{
//some logic
}
#When("I send a request for user type (.+)$")
public void iSendRequestForUserType(String userType)
{
//some logic
}
#Then("I should be able to see the right response$")
public void iShouldBeAbleToSeeTheRightResponse()
{
if(userType.equalsIgnoreCase("xyz")
{
//verify this logic
}
else if(userType.equalsIgnoreCase("abc")
{
//verify that logic
}
}
I know I can use the parameter "userType" in my THEN statement and perform this, but my question is if I do not want to refactor an existing then and still want to verify different behaviours depending on userType set in previous steps.
Any help/direction is appreciated
The recommended way to share state between steps in cucumber-jvm is to use Dependency Injection.
From the Cucumber docs:
"If your programming language is Java, you will be writing glue code (step definitions and hooks) in plain old Java classes.
Cucumber will create a new instance of each of your glue code classes before each scenario.
If all of your glue code classes have an empty constructor, you don’t need anything else. However, most projects will benefit from a dependency injection (DI) module to organize your code better and to share state between step definitions.
The available dependency injection modules are:
PicoContainer (The recommended one if your application doesn’t use another DI module)
Spring
Guice
OpenEJB
Weld
Needle"
While you can declare a variable in your step definitions class to share state between the step definitions, this will only allow you to share between step definitions declared in the same file, and not between files.
As the number of step definition grows, you'll want to group them in some meaningful way, and this approach will no longer suffice.
I did a bit of digging around and found its quite simple.
public class FeatureStepDefinitions{
public Static String globalUserType = null;
#Given("I want to login to system as (.+)$")
public void iWantToLoginToSystemAs(String userType)
{
globalUserType = userType;
//some logic
}
#When("I send a request for user type (.+)$")
public void iSendRequestForUserType(String userType)
{
//some logic
}
#Then("I should be able to see the right response$")
public void iShouldBeAbleToSeeTheRightResponse()
{
if(globalUserType.equalsIgnoreCase("xyz")
{
//verify this logic
}
else if(globalUserType.equalsIgnoreCase("abc")
{
//verify that logic
}
}
Related
I am writing app that uses various REST api endpoints with very similar properties. Only difference is in endpoint adress and payload. Headers, method and other stuff remain the same. That is why I created class to communicate with my remote host, it is called RestApiCommunicator that has method generateRequestAndCallEndpoint(List payload) that wraps payload with all required stuff needed to perform rest call.
Than, I have various classes that only call this communicator class with proper endpoint suffix an its resources.
Everything is working fine but I want to unit test all of those classes. I was trying to figure out how to do that by reading a lot of SO questions but they are rather complicated cases, my is very simple.
I am trying to figure out a proper way to unit test a class that looks like this one:
class MyRestClient {
public void useRestApi(List<MyResources> myResources) {
RestApiCommunicator restApiCommunicator = new RestApiCommunicator ("/some/endpoint");
restApiCommunicator.generateRequestAndCallEndpoint(myResources);
}
}
I want to test if communicator was created with proper enpoint adress and if generateRequestAndCallEndpoint was called exacly once with my sample payload.
Only thing that comes to my mind is that make restApiCommunicator a field, create setter for this field and mock it in Unit tests. But this seems to me as rather dirty solution and I wouldn't like to modify my code to allow tests.
Maybe you can point me in some direction where I could have this class tested using some good pattern.
(ps. If that matters - this is a Spring Boot app)
You could provide a factory for the communicator
class MyRestClient {
private RestApiCommunicatorFactory factory = ...
public void useRestApi(List<MyResources> myResources) {
factory.getCommunicator("/some/endpoint")
.generateRequestAndCallEndpoint(myResources);
}
In your unit test, you provide a mock of the factory, which returns mock communicators. The specific language for that depends on your mocking library of choice.
One way to do exactly what you ask (ie, "to test if communicator was created with proper enpoint adress and if generateRequestAndCallEndpoint was called exactly once with my sample payload") is to mock it using JMockit:
public final class MyRestClientTest {
#Tested MyRestClient restClient;
#Mocked RestApiCommunicator restApi;
#Test
public void verifyUseOfRestApi() {
List<MyResource> resources = asList(new MyResource("a"), new MyResource("b"));
restClient.useRestApi(resources);
new Verifications() {{
new RestApiCommunicator("/some/endpoint");
restApi.generateRequestAndCallEndpoint(resources); times = 1;
}};
}
}
I have a huge Part source code I have to touch at 1 place. It is violating a lot of principles so I would like to extract at least the function I had to modify which is a #UIEventTopic handler. There are no tests and I would like to add them here so I know I do not break existing functionality.
I would like to move away from this:
public class MyPart {
...
#Inject
#Optional
public void event(#UIEventTopic(EVENT) EventParam p) {
...
}
}
To something like this:
public class MyPart {
...
}
public class MyEventHandler {
#Inject
#Optional
public void event(#UIEventTopic(EVENT) EventParam p, MyPart part) {
...
}
}
With the Eclipse DI I see no easy way of creating an instance of the handler class. It cannot be a #Singleton because it is a Part which can have multiple instances, and adding the handler to the IEclipseContext in the #PostConstruct is ugly because it adds a circular dependency between the part and the handler. Is there a magic how I can enforce the instantiation through the e4xmi files, or some alternative way?
My current solution is to extract purely the functionality to a utility bean and return the data and set it on the part, but this is also something not too nice (requires a lot of additional null-checks, ifs, etc.).
I am not entirely sure that I understand your question, however, this is how I would proceed:
Extract Delegate
Move the code in event() to the MyEventHandler so that MyClass fully delegates the event handling
public class MyPart {
#Inject
#Optional
public void event( #UIEventTopic(EVENT) EventParam param ) {
new MyEventHandler().handleEvent( this, param );
}
}
class MyEventHandler {
void handleEvent(MyPart part, EventParam param) {
// all code from event() goes here
}
}
This should be a safe-enough refactoring to do without having tests - and in the end, you don't have a choice as there are no tests.
Ensure the Status Quo
Now I would write tests for handleEvent(), mocking the required methods of MyPart and thus make sure that I won't break existing behavior.
Implement new Feature
After that I would be able to make the desired changes to MyEventHandler::handleEvent in a test driven manner.
Clean Up
Then I would extract an interface from MyPart that has only those methods required for MyEventHandler to do its work. If said interface gets too big, it would indicate that there is more refactoring left to do.
Cucumber: how can you create a BaseSteps class if you can’t use inheritance with Cucumber?
Login Steps inherits the CommonSteps class:
public class LoginSteps extends CommonSteps {
WebDriver driver = getDriver();
#Given("^User navigates to the \"([^\"]*)\" website$")
public void user_navigates_to_the_website(String url) throws Throwable {
basePage.loadUrl(url);
}
#And("^User entered the \"([^\"]*)\" username$")
public void user_entered_the_username(String username) throws Throwable {
loginPage.setUsername(username);
}
public class CommonSteps {
#After
public void close_browser_window(Scenario scenario) throws Exception {
if (scenario.isFailed()) {
scenario.embed(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES), "image/png");
}
}
}
The idiomatic solution in Java, end therefore Cucumber-JVM, is use dependency injection when you want to share state between steps implemented in different classes.
Cucumber support many different dependency injection frameworks. If your project already uses one, it is very likely that your dependency framework is supported.
If you don't use a dependency injection framework, I suggest that you use PicoContainer. If you need to know how to use it, I wrote a blog post describing how to share state between steps.
You can use inheritance, just not with steps for the reason's cited in Roberto Pegoraro's link. I like to organize my steps into different step def files. But this leads to interoperability problems. If you use class variables to communicate between steps then those steps have to be in the same file; unless you use inheritance. I create a UiCommon class to contain the shared class variables (e.g. page file instance variables) that the steps use to communicate between themselves. Each step definition file extends UiCommon. Now it doesn't matter how I refactor the steps definitions between the various step definition files. They can still communicate.
For small projects this isn't usually an issue. But for a large project with multiple test automation engineers who need to minimize git merge conflicts it matters.
I'm building a library that requires some annotation processing to generate code. I now run into an issue that the release build doesn't need to have as much code as the debug build does (since this is a library for modifying configuration variants - primarily used for testing purposes). The following code illustrates the situations. Let's say I want to create a class ConfigManager from some annotated classes and properties. In debug builds, I need this much:
public class ConfigManager {
public Class getConfigClass() {
return abc.class;
}
public void method1() {
doSomething1();
}
public void method2() {
doSomething2();
}
public void method3() {
doSomething3();
}
}
While in release builds, I only need this much:
public class ConfigManager {
public Class getConfigClass() {
return abc.class;
}
}
I have a feeling it may be possible by writing a Gradle plugin to check for build flavor at compile time and invoke a different processor/or somehow pass a parameter to a processor to generate different code. However this topic is pretty new to me so I'm not sure how to achieve this. A couple hours of googling also didnt help. So I'm wondering if anyone could give me a direction or example? Thanks
Pass an option (release=true/false) to your processor.
From javac https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
-Akey[=value]
Specifies options to pass to annotation processors. These options are not interpreted by javac directly, but are made available for use by individual processors. The key value should be one or more identifiers separated by a dot (.).
In combination with Processor.html#getSupportedOptions https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html#getSupportedOptions
Returns the options recognized by this processor. An implementation of the processing tool must provide a way to pass processor-specific options distinctly from options passed to the tool itself, see getOptions.
Implementation outline:
public Set<String> getSupportedOptions() {
Set<String> set = new HashSet<>();
set.add("release");
return set;
}
// -Arelease=true
boolean isRelease(ProcessingEnvironment env) {
return Boolean.parseBoolean(env.getOptions().get("release"));
}
See Pass options to JPAAnnotationProcessor from Gradle for how to pass options in a gradle build.
I have written some code which I thought was quite well-designed, but then I started writing unit tests for it and stopped being so sure.
It turned out that in order to write some reasonable unit tests, I need to change some of my variables access modifiers from private to default, i.e. expose them (only within a package, but still...).
Here is some rough overview of my code in question. There is supposed to be some sort of address validation framework, that enables address validation by different means, e.g. validate them by some external webservice or by data in DB, or by any other source. So I have a notion of Module, which is just this: a separate way to validate addresses. I have an interface:
interface Module {
public void init(InitParams params);
public ValidationResponse validate(Address address);
}
There is some sort of factory, that based on a request or session state chooses a proper module:
class ModuleFactory {
Module selectModule(HttpRequest request) {
Module module = chooseModule(request);// analyze request and choose a module
module.init(createInitParams(request)); // init module
return module;
}
}
And then, I have written a Module that uses some external webservice for validation, and implemented it like that:
WebServiceModule {
private WebServiceFacade webservice;
public void init(InitParams params) {
webservice = new WebServiceFacade(createParamsForFacade(params));
}
public ValidationResponse validate(Address address) {
WebService wsResponse = webservice.validate(address);
ValidationResponse reponse = proccessWsResponse(wsResponse);
return response;
}
}
So basically I have this WebServiceFacade which is a wrapper over external web service, and my module calls this facade, processes its response and returns some framework-standard response.
I want to test if WebServiceModule processes reponses from external web service correctly. Obviously, I can't call real web service in unit tests, so I'm mocking it. But then again, in order for the module to use my mocked web service, the field webservice must be accessible from the outside. It breaks my design and I wonder if there is anything I could do about it. Obviously, the facade cannot be passed in init parameters, because ModuleFactory does not and should not know that it is needed.
I have read that dependency injection might be the answer to such problems, but I can't see how? I have not used any DI frameworks before, like Guice, so I don't know if it could be easily used in this situation. But maybe it could?
Or maybe I should just change my design?
Or screw it and make this unfortunate field package private (but leaving a sad comment like // default visibility to allow testing (oh well...) doesn't feel right)?
Bah! While I was writing this, it occurred to me, that I could create a WebServiceProcessor which takes a WebServiceFacade as a constructor argument and then test just the WebServiceProcessor. This would be one of the solutions to my problem. What do you think about it? I have one problem with that, because then my WebServiceModule would be sort of useless, just delegating all its work to another components, I would say: one layer of abstraction too far.
Yes, your design is wrong. You should do dependency injection instead of new ... inside your class (which is also called "hardcoded dependency"). Inability to easily write a test is a perfect indicator of a wrong design (read about "Listen to your tests" paradigm in Growing Object-Oriented Software Guided by Tests).
BTW, using reflection or dependency breaking framework like PowerMock is a very bad practice in this case and should be your last resort.
I agree with what yegor256 said and would like to suggest that the reason why you ended up in this situation is that you have assigned multiple responsibilities to your modules: creation and validation. This goes against the Single responsibility principle and effectively limits your ability to test creation separately from validation.
Consider constraining the responsibility of your "modules" to creation alone. When they only have this responsibility, the naming can be improved as well:
interface ValidatorFactory {
public Validator createValidator(InitParams params);
}
The validation interface becomes separate:
interface Validator {
public ValidationResponse validate(Address address);
}
You can then start by implementing the factory:
class WebServiceValidatorFactory implements ValidatorFactory {
public Validator createValidator(InitParams params) {
return new WebServiceValidator(new ProdWebServiceFacade(createParamsForFacade(params)));
}
}
This factory code becomes hard to unit-test, since it is explicitly referencing prod code, so keep this impl very concise. Put any logic (like createParamsForFacade) on the side, so that you can test it separately.
The web service validator itself only gets the responsibility of validation, and takes in the façade as a dependency, following the Inversion of Control (IoC) principle:
class WebServiceValidator implements Validator {
private final WebServiceFacade facade;
public WebServiceValidator(WebServiceFacade facade) {
this.facade = facade;
}
public ValidationResponse validate(Address address) {
WebService wsResponse = webservice.validate(address);
ValidationResponse reponse = proccessWsResponse(wsResponse);
return response;
}
}
Since WebServiceValidator is not controlling the creation of its dependencies anymore, testing becomes a breeze:
#Test
public void aTest() {
WebServiceValidator validator = new WebServiceValidator(new MockWebServiceFacade());
...
}
This way you have effectively inverted the control of the creation of the dependencies: Inversion of Control (IoC)!
Oh, and by the way, write your tests first. This way you will naturally gravitate towards a testable solution, which is usually also the best design. I think that this is due to the fact that testing requires modularity, and modularity is coincidentally the hallmark of good design.