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

[Java] Support empty strings and null values in data tables #1857

Merged
merged 3 commits into from
Jan 10, 2020

Conversation

mpkorstanje
Copy link
Contributor

@mpkorstanje mpkorstanje commented Jan 9, 2020

Summary

Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
{name=Aspiring Author, first publication=} or
{name=Aspiring Author, first publication=null}.

 | name            | first publication |
 | Aspiring Author |                   |

Motivation and Context

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

Additionally allowing users to replace empty table cells with a [blank] will
reduce the impact of #1617 and provide a nicer migration pattern.

Details

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@Given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}

Todo

  • Add DataTable.getDataTableConverter method so we can recreate data tables.

Types of changes

  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to not work as expected).

Checklist:

  • I've added tests for my code.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

@coveralls
Copy link

coveralls commented Jan 9, 2020

Coverage Status

Coverage decreased (-0.07%) to 83.95% when pulling 40cb73a on replace-to-empty into 75c8117 on master.

@mpkorstanje mpkorstanje force-pushed the replace-to-empty branch 5 times, most recently from 807e007 to 78e46dd Compare January 10, 2020 15:47
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
@mpkorstanje mpkorstanje added this to the 5.0.0 milestone Jan 10, 2020
@mpkorstanje mpkorstanje marked this pull request as ready for review January 10, 2020 18:12
@fslev
Copy link

fslev commented Feb 13, 2020

Hi,
Is it possible for simillar behavior to apply to the Examples table ?
Regards,

@mpkorstanje
Copy link
Contributor Author

How would that work?

@fslev
Copy link

fslev commented Feb 13, 2020

I believe something like this:

Feature: Test examples feature

  Scenario Template: Examples with empty values
    Given param p="<emptyValue>"
    And param x="<nullValue>"
    Examples:
      | emptyValue | nullValue |
      | [_blank]   |           |

and I think 'replaceWithEmptyString' could be made available also for DefaultParameterTransformer:

@DefaultParameterTransformer(replaceWithEmptyString = "[_blank]")
    public Object defaultTransformer(Object fromValue, Type toValueType) {
        return objectMapper.convertValue(fromValue, objectMapper.constructType(toValueType));
    }

@mpkorstanje
Copy link
Contributor Author

mpkorstanje commented Feb 13, 2020

That's not what Scenario Outlines do.

Scenario Outline: I visit <website>
   Given I visit a <website>

   Examples: Social Media
     | website       | 
     | instagram.com |
     | snapchat.com  |

   Examples: Technology
     | website       | 
     | github.com    |
     | gitlab.com     |

Is syntactic sugar for:

Scenario: I visit  instagram.com 
   Given I visit a instagram.com

Scenario: I visit  snapchat.com 
   Given I visit a snapchat.com

Scenario: I visit  github.com 
   Given I visit a github.com

Scenario: I visit  gitlab.com 
   Given I visit a gitlab.com

and I think 'replaceWithEmptyString' could be made available also for DefaultParameterTransformer:

If I'm not mistaken you can use an optional capture group to do this.

Given param x=true
And param x=false
And param x=

@Given("^param x=(true|false)?$")
public void param(Boolean optional){
   // optional is either true, false or null
}

And with a non-capturing group you can

Given param x="text"
And param x=""
And param x=null

@Given("^param x=(?:null)?(?:\"(.*)\")?$")
public void param(String optional){
   // optional is either text, the empty string, or null
}

@fslev
Copy link

fslev commented Feb 13, 2020

I know, I was referring to the values passed from the examples table to each scenario.
I was wondering if a generic solution for parsing empty/null strings existed in this case. Without re-defining each of my hundreds of step definitions, accordingly.
But I think the simplest solution is to write a little code inside my default parameter transformer, that treats empty strings received from the gherkin feature, either as empty or nulls

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

Successfully merging this pull request may close these issues.

3 participants