I am new to Cucumber and I am using cucumber-java. The cucumber feature files look great. However, the reuse of step definitions really gets in the way about organizing the step definition code. The most intuitive way for me to organize the step definitions is just to follow the organization of the feature files, namely, one class for one feature. However, this way is screwed if there are two identical steps in two feature files, because you will miss one step in one of the classes, which breaks the coherence of the entire structure. However, I cannot convince myself to use other ways right now. So, what is a sensible way to organize step definitions when using cucumber-java?
Thank you very much.
Start with the way you are already doing and once you recognize that a step is reused, move it a class ReUsableSteps or something. This way, if a step does not exist in its class then it should be in ReUsableSteps. Just a thought.
You can have a separate package as placeholder for classes that defines common steps. Add that package as glue.
The best way to use cucumber is to minimize the duplication of step definition. What we should focus on while writing step definition is to avoid any code specific to a class or functionality in steps method of StepDefinition class because that way it can not be generalized, it should have common code which can be used for different steps and code for propagating to separate class for which step is meant and specific logic for each step should reside in separate class. This way we can avoid duplication.
Example:-
Suppose we have component feature file which contains step "Component A has to receive responses", its implementation class is ComponentStepDefinition class, when we implement this in step definition we should not use any logic for iterating or calculating responses for component A there, rather pass the value to a class which performs A related task, in this way to you have to implement "Component B has to receive responses" then same step definition can be used and B's logic will be in another class.
Sort your step definitions by common functionality as related to your domain. They do not have to be linked to specific feature files.
For example, one of our features is to provide our partners with scores (how are they doing on our platform). We have several step definitions related to those scores in a ScoreSteps file. We might have other steps related to partners, those would be in a PartnerSteps file. This also makes it easier to use helper methods related to a certain domain object.
These files would be completely different for you, depending on your domain.
Also note that your IDE will know if a step has already been defined or not (at least, in IntelliJ steps that are undefined are marked in yellow).
Reusing steps is critical for maintenance reasons. That doesn't mean trying to shoehorn steps here and there, but finding a balance between reusability and understanding. As already said above, arranging them into a Common or Reusable package is a pretty good idea. This is something to be done as you go, because you don't always know whether a step is going to be reused or not. In this sense, frequent refactoring of step definitions will be quite normal. Actually it is an indicator of code aliveness, so don't hesitate to make any changes to get the test scenarios clear enough and the testing code as clean as possible. It is just the same well-known coding principles, applied to testing.
One thing that helped me with this task was a utility class (actually it was a set of classes) that allowed me to know which steps and steps definitions exist, the class in which the step definition is defined, the feature files and test scenarios that make use of them, etc. You can even implement advanced options such as searching for steps or steps definitions that contain such and such keywords, or getting to know the step definitions that are not used any longer, etc. Kind of a dictionary.
It can be achieved by either processing the java classes that belong into the 'glue' folder and gather all the regular expressions associated to the gherkin annotations, or by parsing the feature files with the help of a Gherkin parser. Although you may want to have both approaches implemented, as they are not mutually-exclusive; on the contrary, they complement each other.
This is something you may not need when having just a few test scenarios. But as this number grows bigger and bigger, you will find such a mechanism really valuable.
This can be done easily by using multiple test runner classes for multiple feature files.
You can create same steps for different features as long as you are specifying the glue code in your test runner. Glue will make sure the cucumber checks only in the path specified for the steps during execution.
Then you can maintain a suite xml configuration like TestNG.xml for running which all features I want.
#RunWith(Cucumber.class)
#CucumberOptions(monochrome = true, features = "src/test/java/com/abc/batch/xyz/payout/bbq/monthly",
plugin = { "pretty", "html:target/cucumber-html-reports" }, strict = true, glue = {"com.abc.batch.xyz.payout.bbq.monthly" })
#Rollback(false)
The way I organize my cucumber tests are like I have a java package for a cucumber feature where I will have the steps definitions class, feature file, test data files for those tests and Hooks class.
The advantage is that when I try to look for the step definitions in the step class, I know where exactly to look at and the chances of getting a step definition conflict is zero unless you have added the same definition in that package twice.
Related
I am currently writing Selenium WebDriver tests for a variety of websites each using the same proprietary framework.
Because of this, there are many test cases that can be quite similar across different websites. As such I have made my test classes as generic as possible and made it so that every XPath/CSS Selector/ID used to locate elements is defined in a Constants class, which is unique to every project.
But, in some cases, the code for the same test can be the same across different websites, since I wrote them generically.
In addition each test is a direct/indirect extension of a BasicTest class which contains code that is likely to be reused by different tests (ex: WebDriver instance declaration, etc)
The way I thought about setting my test structure was the following:
one generic project that is "reused" by each subsequent project;
one project per website with its own definition of the Constantsclass and a TestSuite class that it can use to run both generic tests and tests specific to itself.
This would allow me not to have copies of these generic tests in each of my test projects.
The problem is that I don't really know how to set this up. The GenericProject is going to contain tests that require variables from Constant, but it makes no sense to have generic Constants. Plus, will I be able to call those tests inside my website project-specific TestSuites? If I redefine Constants in each specific project, will those constants be used for the generic tests defined in GenericProject?
How can I even set it up so that I can reuse Project A's classes inside of Project B, C, D... etc?
Extract your constants to a properties file which exists in each module as src/test/resources/common.properties.
Use org.apache.commons:commons-configuration2 PropertiesConfiguration to read this file. It will handle nested properties just fine.
Common code can be shared by depending on your GenericModule. Official instructions for two models of doing this (extract common tests to a new module or use a test-jar) are here
In general in order to reuse code over projects you would create a library containing the reusable code. In order to do so you'd need to think about a suitable API for the library.
This contains decisions about:
How will functionality be called from dependent code
How will dependent code provide required data.
If you are using constants for e.g. CSS selectors, that are different but have the same semantics, e.g.
root frame
side panel
main area
...
you might want to define an interface that the dependent code can provide. This could look like:
interface CssSelectors {
String rootFrame();
String sidePanel();
//...
}
If you are building this for tests you might also want to use features of your test framework (e.g. Rules in JUnit).
When reusing code in tests you also should consider another aspect:
If s.o. reads the tests written with your library, will she be able to sufficiently understand what is happening behind the border of the library to understand what the test is all about? This is a lot more of a question when dealing with test code than with production code as for test coverage and validity of tests it often matters a lot more how a setup or verification is done than is the case for production code.
I have created two micro-services using java. I need to make a REST api call from service A to service B. The data sent will be in JSON format. Using jax-rs I need to create entity class in both the service.
Since both the entity class be same in both the projects. Do i
Create an common jar and use is for all my entity/domain objects? Does this make my microservice more tightly coupled?
Do i create the same class in both the microservice projects? This will just mean repeating the work in both the projects?
Is there a better way to communicate between the sevices?
In terms of having your two micro services independent and having them also independent in the future I would also duplicate the code. We had the exact same situation before. Several microservices seem to use some "common" classes that can be put to a seperate jar.
In the end we had following situation:
several (5+) services using the same JAR
turned out that classes that we thought are the same, seemed to have slightly different semantics in different services
a change on one of the classes more or less forced us to have a release on every microservice, when it came to releasing (no independency here anymore)
developers tend to see "common" behavior everywhere, so you most likely end up with some "Helper/Utility" classes there as well which is in the meanwhile considered a code smell in OOP
Long story short, in the meanwhile we switched to having the code duplicated, which gives us the freedom to handle our mircoservices really independently, as we only need to stick to the service contract. What happens internally is fully up to the service and we don't have to release all services in the end of an iteration. I'm not saying that the other option is wrong, but it turned out that it was not suitable for us. If you really see common classes between two services and you are sure you don't mess your common library up with other crap, your save to go.
EDIT
Maybe as follow up, we had the same discussion in regards of tests (unit and integration) having share test code in some common classes. In the end this was hell, as every slight change in code or acceptance criteria made 50% of tests fail. Meanwhile our strategy is to not share anything on test level and have everything right at the tests place. By that you are super fast in eliminating or changing tests. In the end the lesson for us was to keep business code as clean and elegante as suitable and the test code in a way to give us the least headache possible.
Edit2
Meanwhile, we define all our REST interface with open api specifications and create the actual DTO objects that are exchanged via the maven plugin openapi-generator. The spec resides in the project that implements the interface and it is published to artifactory. The project implementing the client pulls it and creates DTOs based on that. By that, you have a single point of truth and no need to write DTO boilerplate code.
I'd say it depends on the situation. If you use a shared package, this will introduce a coupling between the two projects. This makes sense, if both of the project build up on the same data classes and therefore will have the same dto objects to work with. Ideally you would have your own nexus which simplifies the usage of the shared artefact.
Otherwise, if only a few classes are redundant I probably would implement it in each sevice separately, which decouples them too.
I am afraid that you need to decide which one the right solution is for your project.
This is common situation where we as developer gets confused. I would suggest to have a common jar(shared) which can be used in both micro services (A and B). It is nothing but sharing a third resource as we use third-party libraries.
In my current project we were in the same situation and we found the best approach to have separate shared libraries(api-shared as name) and consuming it as jar in different micro-services.
In your second approach you ended up with redundant code and also difficult to maintain. Lets say if you have any changes in entity then you have to change in both the entities which is not quite a good way to synchronize the thing.
All in all I would suggest you to use shared jar for both micro services.
Regards
Techno
first of all - I am not sure if cucumber support this, but is it possible to define features in different module than in one that contains feature files?
Given real life example:
Let's say I want to have module called 'carcore',
Then let's say I want to have module called 'Volkswagen',
and other one called 'Ford'.
Is it possible that I will put feature deffinition files for common features in 'carcore' module but keep feature diffinition files specific for vokswagen or ford in their own modules?
I am using gradle to sew this modules together. It is more or less simple. Though when Cucumber annotations are introduced, it is not that easy. Cucumber is not able to find feature definitions in other modules. I was not able to find any relevant and useful reading, so if anyone can help me or point me into right direction I would be very glad.
Cucumber is designed so that you have one World for your features, and in that world each thing you talk about should have a unique name and a single definition. It deliberately chooses to not have any kind of name-spacing. The rationale behind this is that Cucumber is a tool for describing business behaviour not for programming.
What you are doing with your modules is programming, and what you seem to reflecting is HOW your program is implemented, but HOW has no place in Cucumber scenarios; they should be written way before you think about HOW to do things. Scenarios should only be about WHAT the business wants and WHY they want this.
What you can do with your modules idea is push it down your stack, into the step definitions or better yet modules that define calls that your step definitions can use. Now because you are in a programming language you have the power to program in whatever way you need.
Finally Ford and Volkswagen are brands of Car. Whilst you might use the names as examples having a module for an individual brand seems wrong at any level.
It is done automatically as with any other classes.
Cucumber will pick up automatically any feature definition files that are in defined dependencies.
My IDE didn't picked up the relation between feature definition file and feature itself, so it got me confused.
We are considering to use Cucumber on our project for acceptance testing.
When we write a scenario in a Cucumber feature, we write a list of Given, When and Then statements.
As we use cucumber-jvm project, the Given, When and Then statement are related to Java methods in (JUnit) classes.
I want to know what is the best organization for the code related to Given / When / Then in the project structure. My main concern is the maintenance of the cucumber tests on a big project, where the number of scenario is quite important, and especially regarding the items that are shared between features.
I can see at least 2 main approaches:
Each feature is related to it's own JUnit class. So if I have a foo/bar/baz.feature cucumber file, I will find the releated foo.bar.Baz JUnit class with the adequate #Given, #When and #Then annotated methods.
Separate #Given, #When and #Then methods into "thematic" classes and packages. For example, if in my cucumber scenario I have a statement Given user "foo" is logged, then the #Given("^user \"([^\"]*)\" is logged$") annotated method will be located in the foo.user.User class method, but potentially, the #When method used later in the same cucumber scenario will be in a different Java class and package (let say foo.car.RentCar).
For me, the first approach seems good in the way that I can easily do the relation between my cucumber features and my Java code. But the drawback is that I can have a lot of redundancies or code duplication. Also, it may be hard to find a possible existing #Given method, to avoid to recreate it (the IDE can help, but here we are using Eclipse, and it does not seem to give a list of existing Given statement?).
The other approach seems better essentially when you have Given conditions shared among several cucumber feature, and thus I want to avoid code duplication. The drawback here is that it can be hard to make the link between the #Given Java method and the Given cucumber statement (maybe, again, the IDE can help?).
I'm quite new to cucumber, so maybe that my question is not a good question, and with time and experience, the structure will be self-evident, but I want to get good feedbacks on its usage...
Thanks.
I would suggest grouping your code according to the objects it refers to, similar to option #2 you presented in your question. The reasons being:
Structuring your code based on how and where it's being used is a big no-no. It's actually creating coupling between your feature files and your code.
Imagine such a thing in your product's code- the SendEmail() function wouldn't be in a class called NewEmailScreenCommands, would it? It would be in EmailActions or some such.
So the same applies here; structure your code according to what it does, and not who uses it.
The first approach would make it difficult to re-organize your feature files; You'd have to change your code files whenever you change your feature files.
Keeping code grouped by theme makes DRYing it much easier; you know exactly where all the code dealing with the user entity is, so it's easier for you to reuse it.
On our project we use that approach (i.e BlogPostStepDefinitions class), with further separating the code, if the class gets too large, to types of steps (i.e BlogPostGivenStepDefinitions).
We have also started using Cucumber-JVM for acceptance testing and have similar problems with organising code. We have opted to have 1 step definition class for each feature. At the moment this is fine as the features we are testing aren't very complex and quite separate, there is very little overlap in our features.
The second approach you mentioned would be better I think, but it is often challenging to tie together several different step definition classes for a single scenario. I think the best project structure will become clearer once you start adding more features and refactor as normal.
In the meantime here is an Eclipse plugin for cucumber,
https://github.com/matthewpietal/Eclipse-Plugin-for-Cucumber
it has syntax highlighting as well as a list of existing available steps when writing a feature.
On the current project I am taking part in, we asked ourselves the very same question.
After fiddling a bit with the possibilities, what we opted for was a mix of both the solutions you exposed.
Have steps regrouped in theme-centric common steps classes
app-start steps
security check steps
[place random feature concern here] steps
And classes of scenario (and in some case even feature) specific steps
This was to have at the same time the grouping of factorized code which is pretty easily identifiable on it's whatabouts, whereabouts and whatnot.
Yet it allows not to clutter those common classes with overly specific code.
The wiring between all these classes is handled by spring (with cucumber spring which does a great job once you get the hang of it).
I've got 2 questions about organising Unit tests.
Do I have to put test to the same package as tested class, or can I organise tests in different packages?
For example if I have validity and other tests, is it correct to split them into different packages, even if they are for same class?
What about mock and stub classes? Shall I separate them from packages containing only tests, or put them together?
The way we do our JUnit test cases is to put them in the same package, but in a different root directory. Since we use Maven, we just use the standard locations making the structure similar to the following.
src/main/java/com/foo/Bar.java
src/test/java/com/foo/BarTest.java
Obviously there's more to the structure, but this lets us build the tests separately from the mainline code, but still access protected classes and the like. With respect to different types of tests, this is very subjective. When we started our testing effort (which unfortunately started after development), I tried to keep things pretty isolated. Unfortunately, it quickly became a nightmare when we got to the 500+ test case point. I've since tried to do more consolidation. This led to reduced amounts of code to maintain. As I said, though, it's very subjective.
As far as test-only code, we keep it in a separate com.foo.test package that resides only in the src/test/java tree.
I too tend to put my tests in the same package but under a different root directory. This allows me to test package-private classes or access packing-private classes while testing something else in the package. They are kept in a separate directory tree to allow excluding them from the deployed result (in particular to ensure that test code didn't accidentally get into production code). What matters most, however, is what works for your situation.
In terms of how many test classes per production class, the theory I've seen is that you write one test class per fixture, that is per setup structure. In many cases that is the same (or close enough) to one test class per production class, but I have sometimes written more test classes (in particular equality tests tend to be separated) for a give production class, and occasionally one test class of for a group of (related) production classes (say, for testing the Strategy pattern).
Mostly, I don't worry too much about the theory, but rework the tests as needed to keep duplication to an absolute minimum.
Keeping it the same package allows you to use package-private visibility for code that is intended to be accessed via the test only.
Regarding using separate root directories, that is a good practice. It also has an advantage for us, since we use IDEA, IDEA recognizes that production code cannot reference test code.
In terms of keeping them separate, there is a great power in having one, and only one, test class per production class at the unit level. Of course, some classes get created in production as part of refactoring that have no test classes at all, and that is fine, but when you want to know what test tests a certain class, having a convention that says ClassNameTest is the tests for ClassName is very helpful.
TestNG is much friendlier to this paradigm than JUnit, though.
Test classes should be rather in different packages, it's easier to separate them from the production code when you package it for release. I usually keep lots of test fluff in those packages, all sorts of mocks, configurations, scenarios.. But when you build - it doesn't get it. In some situations, it's a good idea to keep your testing stuff even in different projects. Depends.