Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for record classes in data providers #2241

Open
mcimadamore opened this issue Feb 6, 2020 · 4 comments
Open

Add support for record classes in data providers #2241

mcimadamore opened this issue Feb 6, 2020 · 4 comments
Labels

Comments

@mcimadamore
Copy link

mcimadamore commented Feb 6, 2020

It would be nice if testng supported the newly added records feature, as a means to replace Object arrays in data providers. Record types [1] are simple data carriers, which can contain any data. They are better suited at modelling parameter lists than Object[] for a number of reasons:

  • records are nominal, and strongly typed - which leads to more readable and safer code
  • records support primitive fields too (no need to box primitives into Object)
  • records have good reflection support - meaning that - at runtime - it is possible to query the types of record components

This would enable not only test writers to write better code, but also for the testng framework to become more robust (since testng could cross-validate the record component types against the parameter types of a given test method using a data provider). Similarly, IDEs could take advantage of the added type safety and highlight mismatches between data providers and tests.

Expected behavior

record R(int x, String s);

public List<R> dataProvider() {
    return List.of(
               new R(1,"one"),
               new R(2,"two"));
}

Actual behavior

public Object[][] dataProvider() {
        return new Object[][] {
             { 1, "one" },
             { 2, "two" },
        };
    }

[1] - https://openjdk.java.net/jeps/359

@juherr
Copy link
Member

juherr commented Feb 28, 2020

@mcimadamore Did you try it? What was the issue?
I think it could already work.

@mcimadamore
Copy link
Author

I did not try - note that it will require changes to the testng data provider mechanism so that it will support record types natively. In other words, the above describes a possible suggestion for an enhancement to the testng framework to take advantage of some of the newer Java features.

@juherr
Copy link
Member

juherr commented Feb 28, 2020

Data providers accept Iterators and I don't see why it can't work with an iterator of records.

@mcimadamore
Copy link
Author

If I'm not mistaken, the Iterator support currently goes like

@DataProvider
Iterator<Object[]> dataProvider() { ... }

While Iterator<Object[]> is slightly better than Object[][], you still have the problems described in my original issue:

  • there is no way to statically check that the test method is working with the right number of arguments and that the arguments have types that match those supplied by the provider

  • the data provider code will still have to box all the arguments up in an Object array

The solution I've sketched uses a record - which you can think of as a named tuple - to model the Object[] part of the data provider (that is, the set of arguments to be passed to a single test method call).

So, if Person is a record like this:

record Person(int age, String name);

a data provider could return either:

  • Person[]
  • Iterator<Person>
  • List<Person> (but perhaps this variant feels a little redundant)

Then your test can still be something like:

@Test
void m(int age, String name) { ... }

Much easier to see if the data provider agrees with the test method, and also easy for testNG to reflectively unpack the record Person into the two components (age and name) and pass those to the test method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants