Writing DRY Spock tests - groovy

Assume that I have a Spock specification that given a city and state tests for the correct zip code. Assume I have a text file of cities and states that is used to drive the tests in the where clause.
Now assume that I want to split the tests so that I can run for "Virginia" or "Maryland". The approach that I have taken is to create a new VirginiaSpec and a new MarylandSpec and in that spec, I modify the where clause.
This works, but seems inefficient because every other part of the VirginiaSpec and MarylandSpec is exactly the same. In addition, if the logic changes, then I would need to change it in every spec that I have.
So what I am looking for is an approach that allows me to have one StateSpec in which the where clause can be parameterized.
I realize I have not included a code example, however if my question is not clear, then I can provide one. Thanks for your help.
-Dan

You have a couple of options. You could put the basic setup and structure and even the test itself in a base test class, then extend that class w/ your VirginiaSpec and MarylandSpec. Your spec classes would be very small probably just defining a constant that is the state for the spec.
But that seems needless. If both the cities and states are in this file, you could just read in the file in the where section of your test.
https://snekse.github.io/test-often-and-prosper-slides/#/42
If you cannot get the WHERE section working, you could always read in your file during the setupSpec and store the data in some kind of data structure then loop through it.
Spock: Reading Test Data from CSV File
But in general, using the Where label is going to be the right answer.

Related

Should Spark transformation be broken to functions

It looks like all the Spark examples found in web are built in as single long function (usually in main)
But it is often the case that it makes sense to break the long call into functions like:
Improve readability
Share code between solution paths
A typical signature would look like this (this is Java code but similar signature would appear in all languages)
private static Dataset<Row> myFiltering(Dataset<Row> data) {
return data.filter(functions.col("firstName").isNotNull()).filter(functions.col("lastName").isNotNull());
}
The problem here is that there is no safety for the content of the Row, as there is no enforcement on the fields, and calling the function becomes not only a matter of matching the singnature but also the content of Row. Which obviously may (and does in my case) cause errors.
What is the best practice you enforce in large scale development environments? do you leave the code as one long function? do you suffer every time you change field names?
Yes, you should split your method into smaller methods. Be aware, that many small functions also are not much readable ;)
My rules:
Split some chain of transformation if we can name it - if we have name, it means that this is some kind of subfunction
If there are many functions of the same domain - extract new class or even package.
KISS: don't split if your function call chain is short and also describes some subfunction, even if some lines may be extracted - it is not as much readable to read many many custom functions
Any larger - not in 1-3 lines - filters, maps I suggest to extract to method and use method reference
Marked as Community Wiki, because this is only my point of view and it's OT for StackOverflow. It someone else has any other suggestions, please share it :)

TestNumberer in OrigenTesters?

I see that there is a TestNumberer class in the OrigenTesters at https://github.com/Origen-SDK/origen_testers/blob/master/lib/origen_testers/generator/test_numberer.rb . However, it looks pretty bare, and doesn't look like its being used internally anywhere. So, my question is does this TestNumberer... do anything? I don't see anything in the guides about automatically generating test numbers. What I'd like is something like:
test_numberer.set_base(1000) # for example
test_numberer.set_offset(5)
func (..., test_number: test_numberer.next) #=> test_number = 1000
func (..., test_number: test_numberer.next) #=> test_number = 1005
Possibly even embed incrementing the test number into the func function itself in the interface.
Thanks!
(For the record, I actually already have this in one of my apps for personal use, but am wondering if OrigenTesters already has one, and if not, if it could use one)
No, that is old and dead code which should be removed.
There is a solution for generating test numbers though, and that is the TestIds plugin: http://origen-sdk.org/test_ids/
I'm still not totally happy with how it works, but I use it in production today in a large test flow module.
I would say it does solve these problems effectively:
How do you assign test (and/or bin) numbers within an IP test block, in such a way that it can be included in different SoC test programs which may each want to assign a different range or even a different numbering scheme to the tests for that IP.
How do you automatically assign test (and/or bin) numbers in such a way that they will stick and won't change when other tests are added or removed from the flow in future.
I don't really have anything specific that I know is wrong with it, just some niggles that have come up from time to time and it would be good to get other people using it and involved with it to help iron these out.
One of the things that I have come to realize is that it is easier to manage if you explicitly give tests a number (or bin) ID in the test flow like this:
func :blah, number: :blah_test1
func :blah, number: :blah_test2
This makes it easier to control when you want same-named tests to have the same number or not, whilst not locking down to any particular number.
Anyway, you should find the documentation of it pretty good and obviously ask further questions here if you have any.

How to capture a text from the cucumber result after executing a feature file and pass it to another feature file as a test data?

I have a feature file A.feature which generates a number in the response body. Now, I have to capture that text/number and then pass it as test data to another feature file.Do we need to write step definition or is there any other way?Please suggest.
Generally, you should not do that. In fact you should try to make your test cases totally independent from each other. It's a bad sign if a single code change breaks many of your tests (in your case, whenever the first feature breaks, the second one would as well.) It's also a bad sign that, as a starting point, your second feature needs a special response that is not easy to construct.

Is there a way to run a cucumber scenario multiple times over a list of dynamically generated data?

For example, I have a list of ids for a product that lives in a database and is updated daily. I need to be able to run a scenario that consumes that data and runs the same steps over each of the ids in order. However, the test should not stop because one of the ids failed in the scenario, similar to what cucumber does with the scenario outline type of tests.
We would also want to format the output of the cucumber test(s) so that each id is formatted as if it is a separate test or example in a "scenario outline."
I believe I did something similar some time ago. Have a look at this feature definition.
The "Then I should be able to get to the browse categories page" action is defined here and, as you can see, Category at line 59 retrieves data from this class. In this case I'm getting data from a CSV file, but you can just substitute it with your DB.
My Ruby is a bit basic so the code style might not look so good, but it is an example I had around to easily explain what I did. Hope this help!
Cucumber is not designed to write complex information in feature file ,
If your Data is complex , or dynamically generated , you should get Data in step definition and write a generic term in feature file .
That's the intention of cucumber , writing simple features so that non technical person can easily understand what the scenario is doing.

How do I create an array of resources using Jena?

I am using Jena and Java, and am reading a CSV file. For each line of the file there is a subject resource. Two subject resources, on adjacent lines, might have share the same value of a field in the line (e.g: both lines have the same process id). In this case, I need to combine the two subject resources as each one represents a sub-process in production (for example).
My question is: how can I reference those two resources dynamically so that I can combine them? I came to the idea that when I find that they share the same property to store them in an array resource subjects. Is it the right approach?
This question would be a lot easier to answer if you could show some sample data. As it is, I think you're focusing on the wrong bit of the question. If you can decide clearly what it means to have two rows in your CSV with identical process, and then you decide how you're going to encode that meaning in your RDF model, then the question of how to write the code - as an array or whatever - will be much clearer.
For example (and I'm going to make up some data here - as I said, it would be easier if you show an actual example), suppose your CSV contains:
processId,startTime,endTime
123,15:22:00,15:23:00
123,16:22:00,16:25:00
So process 123 has, apparently two start and end time pairs. If you model this naively in RDF, you'll end up with a confusing model:
process:process123
a :Process;
process:start "15:22:00"^^xsd:time;
process:end "15:23:00"^^xsd:time;
process:start "16:22:00"^^xsd:time;
process:end "16:25:00"^^xsd:time;
.
which would suggest that one process had two start times (and two end times) which looks nonsensical. However, it might be that in reality you have a single process with multiple episodes, suggesting one way to model it, or a periodic process which occurs at different times, or, as you suggested, sub-processes of a parent process. Or something else entirely (I'm only guessing, I don't know your domain). Once you are clear what the data means, you can produce a suitable RDF model. For example, an episodic process might be:
process:process123
a :Process;
process:episode [
a process:Episode;
process:start "15:22:00"^^xsd:time;
process:end "15:23:00"^^xsd:time;
];
process:episode [
a process:Episode;
process:start "16:22:00"^^xsd:time;
process:end "16:25:00"^^xsd:time;
]
.
Once the modelling is clear in your mind, I think you can see that the question of how to produce the desire RDF triples from Java code - and whether or not you need an array - is much clearer. Equally importantly, you can think in terms of the JUnit tests you would write to test whether your code is behaving correctly.

Resources