henriquels
henriquels

Reputation: 546

Spock Extension - Extracting variable names from Data Tables

In order to extract data table values to use in a reporting extension for Spock, I am using the following code:

@Override
public void beforeIteration(IterationInfo iteration) {
    Object[] values = iteration.getDataValues();
}

This returns to me the reference to the objects in the data table. However, I would like to get the name of the variable that references the value.

For example, in the following test:

private static User userAge15 = instantiateUserByAge(15);
private static User userAge18 = instantiateUserByAge(18);
private static User userAge19 = instantiateUserByAge(19);
private static User userAge40 = instantiateUserByAge(40);

def "Should show popup if user is 18 or under"(User user, Boolean shouldShowPopup) {
        given: "the user <user>"

        when: "the user do whatever"
        ...something here...

        then: "the popup is shown is <showPopup>"
        showPopup == shouldShowPopup

        where:
        user        | shouldShowPopup
        userAge15   | true    
        userAge18   | true    
        userAge19   | false    
        userAge40   | false    

}

Is there a way to receive the string “userAge15”, “userAge18”, “userAge19”, “userAge40” instead of their values?

The motivation for this is that the object User is complex with lots of information as name, surname, etc, and its toString() method would make the where clause unreadable in the report I generate.

Upvotes: 1

Views: 644

Answers (1)

kriegaex
kriegaex

Reputation: 67407

You can use specificationContext.currentFeature.dataVariables. It returns a list of strings containing the data variable names. This should work both in Spock 1.3 and 2.0.

Edit: Oh sorry, you do not want the data variable names ["a", "b", "expected"] but ["test1", "test1", "test2"]. Sorry, I cannot help you with that and would not if I could because that is just a horrible way to program IMO. I would rather make sure the toString() output gets shortened or trimmed in an appropriate manner, if necessary, or to (additionally or instead) print the class name and/or object ID.

Last but not least, writing tests is a design tool uncovering potential problems in your application. You might want to ask yourself why toString() results are not suited to print in a report and refactor those methods. Maybe your toString() methods use line breaks and should be simplified to print a one-line representation of the object. Maybe you want to factor out the multi-line representation into other methods and/or have a set of related methods like toString(), toShortString(), toLongString() (all seen in APIs before) or maybe something specific like toMultiLineString().


Update after OP significantly changed the question:

If the user of your extension feels that the report is not clear enough, she could add a column userType to the data table, containing values like "15 years old".

Or maybe simpler, just add an age column with values like 15, 18, 19, 40 and instantiate users directly via instantiateUserByAge(age) in the user column or in the test's given section instead of creating lots of static variables. The age value would be reported by your extension. In combination with an unrolled feature method name using #age this should be clear enough.

Is creating users so super expensive you have to put them into static variables? You want to avoid statics if not really necessary because they tend to bleed over side effects to other tests if those objects are mutable and their internal state changes in one test, e.g. because someone conveniently uses userAge15 in order to test setAge(int). Try to avoid premature optimisations via static variables which often just save microseconds. Even if you do decide to pre-create a set of users and re-use them in all tests, you could put them into a map with the age being the key and conveniently retrieve them from your feature methods, again just using the age in the data table as an input value for querying the map, either directly or via a helper method.

Bottom line: I think you do not have to change your extension in order to cater to users writing bad tests. Those users ought to learn how to write better tests. As a side effect, the reports will also look more comprehensive. 😀

Upvotes: 1

Related Questions