Skip to content

Commit

Permalink
Make quote character in @CsvSource configurable
Browse files Browse the repository at this point in the history
Prior to this commit, the quote character for quoted strings in
@CsvSource was hard coded to a single quote (') and could not be
changed; however, with the recently added support for text blocks, it
may be desirable to change the quote character to something else.

This commit introduces a new quoteCharacter attribute in @CsvSource
that allows the user to change the quote character. The quoteCharacter
defaults to a single quote for backward compatibility.

Closes #2735
  • Loading branch information
sbrannen committed Oct 2, 2021
1 parent 10f8ceb commit f1cbfbe
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ GitHub.

==== New Features and Improvements

* ❓
* The quote character for _quoted strings_ in `@CsvSource` is now configurable via the new
`quoteCharacter` attribute, which defaults to a single quote (`'`) for backward
compatibility.


[[release-notes-5.8.2-junit-vintage]]
Expand Down
15 changes: 8 additions & 7 deletions documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1363,13 +1363,14 @@ The default delimiter is a comma (`,`), but you can use another character by set
`String` delimiter instead of a single character. However, both delimiter attributes
cannot be set simultaneously.

`@CsvSource` uses a single quote `'` as its quote character. See the `'lemon, lime'` value
in the example above and in the table below. An empty, quoted value `''` results in an
empty `String` unless the `emptyValue` attribute is set; whereas, an entirely _empty_
value is interpreted as a `null` reference. By specifying one or more `nullValues`, a
custom value can be interpreted as a `null` reference (see the `NIL` example in the table
below). An `ArgumentConversionException` is thrown if the target type of a `null`
reference is a primitive type.
By default, `@CsvSource` uses a single quote `'` as its quote character, but this can be
changed via the `quoteCharacter` attribute. See the `'lemon, lime'` value in the example
above and in the table below. An empty, quoted value `''` results in an empty `String`
unless the `emptyValue` attribute is set; whereas, an entirely _empty_ value is
interpreted as a `null` reference. By specifying one or more `nullValues`, a custom value
can be interpreted as a `null` reference (see the `NIL` example in the table below). An
`ArgumentConversionException` is thrown if the target type of a `null` reference is a
primitive type.

NOTE: An _unquoted_ empty value will always be converted to a `null` reference regardless
of any custom values configured via the `nullValues` attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ class CsvParserFactory {

private static final String DEFAULT_DELIMITER = ",";
private static final String LINE_SEPARATOR = "\n";
private static final char SINGLE_QUOTE = '\'';
private static final char DOUBLE_QUOTE = '"';
private static final char EMPTY_CHAR = '\0';
private static final boolean COMMENT_PROCESSING_FOR_CSV_SOURCE = false;
private static final boolean COMMENT_PROCESSING_FOR_CSV_FILE_SOURCE = true;

static CsvParser createParserFor(CsvSource annotation) {
String delimiter = selectDelimiter(annotation, annotation.delimiter(), annotation.delimiterString());
return createParser(delimiter, LINE_SEPARATOR, SINGLE_QUOTE, annotation.emptyValue(),
return createParser(delimiter, LINE_SEPARATOR, annotation.quoteCharacter(), annotation.emptyValue(),
annotation.maxCharsPerColumn(), COMMENT_PROCESSING_FOR_CSV_SOURCE,
annotation.ignoreLeadingAndTrailingWhitespace());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
* <p>The column delimiter (defaults to comma) can be customized with either
* {@link #delimiter} or {@link #delimiterString}.
*
* <p>{@code @CsvSource} uses a single quote ({@code '}) as its quote character.
* See the {@code 'lemon, lime'} examples in the documentation for the {@link #value}
* <p>By default, {@code @CsvSource} uses a single quote ({@code '}) as its quote
* character, but this can be changed via {@link #quoteCharacter}. See the
* {@code 'lemon, lime'} examples in the documentation for the {@link #value}
* and {@link #textBlock} attributes. An empty, quoted value ({@code ''}) results
* in an empty {@link String} unless the {@link #emptyValue} attribute is set;
* whereas, an entirely <em>empty</em> value is interpreted as a {@code null} reference.
Expand Down Expand Up @@ -126,6 +127,21 @@
@API(status = EXPERIMENTAL, since = "5.8.1")
String textBlock() default "";

/**
* The quote character to use for <em>quoted strings</em>.
*
* <p>Defaults to a single quote ({@code '}).
*
* <p>You may change the quote character to anything that makes sense for
* your use case; however, the primary use case is to allow you to use double
* quotes in {@link #textBlock}.
*
* @since 5.8.2
* @see #textBlock
*/
@API(status = EXPERIMENTAL, since = "5.8.2")
char quoteCharacter() default '\'';

/**
* The column delimiter character to use when reading the {@linkplain #value lines}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@
class ParameterizedTestIntegrationTests {

@ParameterizedTest
@CsvSource(textBlock = """
@CsvSource(quoteCharacter = '"', textBlock = """
apple, 1
banana, 2
'lemon, lime', 0xF1
"lemon, lime", 0xF1
strawberry, 700_000
""")
void executesLinesFromTextBlock(String fruit, int rank) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ CsvSource build() {
// @CsvSource
when(annotation.value()).thenReturn(this.lines);
when(annotation.textBlock()).thenReturn(this.textBlock);
when(annotation.quoteCharacter()).thenReturn('\'');

return annotation;
}
Expand Down

0 comments on commit f1cbfbe

Please sign in to comment.