0

I have many boolean methods like boolean isPalindrome(String txt) to test.

At the moment I test each of these methods with two parameterised tests, one for true results and one for false results:

    @ParameterizedTest
    @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
    void test_isPalindrome_true(String candidate) {
        assertTrue(StringUtils.isPalindrome(candidate));
    }
    
    @ParameterizedTest
    @ValueSource(strings = { "peter", "paul", "mary is here" })
    void test_isPalindrome_false(String candidate) {
        assertFalse(StringUtils.isPalindrome(candidate));
    }

Instead I would like to test these in one parameterised method, like this pseudo Java code:

    @ParameterizedTest
    @ValueSource({ (true, "racecar"),(true, "radar"), (false, "peter")})
    void test_isPalindrome(boolean res, String candidate) {
        assertEqual(res, StringUtils.isPalindrome(candidate));
    }

Is there a ValueSource for this? Or is there an other way to achieve this in a concise manner?

halloleo
  • 9,216
  • 13
  • 64
  • 122
  • Have a look at https://www.baeldung.com/parameterized-tests-junit-5 - there are some ideas there that might be useful to you. In particular, the CsvSource annotation might be just what you need. – Dawood ibn Kareem Aug 02 '22 at 02:42
  • @DawoodibnKareem The CsvSource is pretty cool. Thanks! - Anyway to pass in null as a cell value through the CsvSource string "interface"? – halloleo Aug 02 '22 at 06:48
  • 1
    I don't think you can use CsvSource to explicitly pass null. You might have to fudge it with some logic in your test. Like, for example, if `"*"` is passed, replace it with null. Or something like that. – Dawood ibn Kareem Aug 02 '22 at 07:29
  • 1
    Additionally, I actually think your first excerpt above, with two separate tests, is the right way to test this. Just my opinion of course. But essentially, you want to (1) test that the method returns true when the input IS a palindrome; and (2) test that the method returns false when the input IS NOT a palindrome. That feels like two separate tests to me. – Dawood ibn Kareem Aug 02 '22 at 07:33
  • @DawoodibnKareem Your comments make all sense. Do you want to make an answer out of it? (If not, I'm happy to do so.) – halloleo Aug 02 '22 at 08:52
  • I don't think my comments quite add up to an answer. I gave you a link with some good information, and a couple of opinions. I didn't answer your question. If you think you can turn all of that into a proper answer that would be useful to others, then go for it. – Dawood ibn Kareem Aug 02 '22 at 08:56

1 Answers1

1

Through the very helpful comment from Dawood ibn Kareem (on the question) I got a solution involving @CsvSource:

    @ParameterizedTest
    @CsvSource(value = {"racecar,true", 
                        "radar,true", 
                        "peter,false"})
    void test_isPalindrome(String candidate, boolean expected) {
        assertEqual(expected, StringUtils.isPalindrome(candidate));
    }

I quite like: Although the code uses strings to express boolean types, it is quite compact and keeps things together which IMHO belong together.

Read about @CsvSource here.

halloleo
  • 9,216
  • 13
  • 64
  • 122