1

I'd like to validate an expected response against an actual from an actual API response as part of my unit tests.

So I have this:

Expectation:

disqualified because taxpayer can be claimed as dependent

I'd like to assert against this:

Actual:

disqualified because you can be claimed as a dependent

API response from a compiled binary.

Since these pieces of text are close enough, I'd like to pass this assertion I have in my test:

Assert.assertEquals(titleText.toLowerCase(), t.toLowerCase(), "Did not match!");

Since this assertion obviously did not pass because the 2 pieces of text are not equal.

I tried this instead:

Assert.assertTrue(titleText.toLowerCase().contains(t.toLowerCase()));

But the test still fails....How can I make this test pass? Any suggestions would be much appreciated.

mosawi
  • 1,283
  • 5
  • 25
  • 48
  • assert how? either they are equal, or they are not. Of course the test still fails, because there are words in between,so it doesn't 'contain' that exact String. You'll need to write your own logic here. split your smaller String in words, check for the occurence of each of them, and check how much difference there is with the other one. How? that depends on your requirements, so you can't ask us that – Stultuske Oct 08 '15 at 06:54
  • 1
    `assertTrue(titleText.startsWith("disqualified because ") && titleText.endsWith("can be claimed as a dependent"))`? – Tagir Valeev Oct 08 '15 at 07:00
  • Thanks @TagirValeev but I'd like something more generic to work with all my tests – mosawi Oct 08 '15 at 07:04
  • Thanks @Stultuske I'm looking into doing a String array comparison, if 2 or more items in this string array do not equal, I could fail the test. – mosawi Oct 08 '15 at 07:06
  • @TagirValeev or just [.matches("(?i)disqualified because \\w+ can be claimed as dependent")](http://stackoverflow.com/a/33009235/256196) – Bohemian Oct 08 '15 at 07:27

4 Answers4

2

You will have to write comparator of your own.

class OwnComparator {
    public static boolean checkThoseForEquality(String str1, String str2) {
        // your logic goes here
    }
}

Use it with

 assertTrue(OwnComparator.checkThoseForEquality(titleText, t);

You can even move toLowerCase() from code to this comparator, making your general code shorter.

I don't think expecting testNG to have implemented exactly what you mean by "almost equal" is valid.

zubergu
  • 3,646
  • 3
  • 25
  • 38
1

The best approach would probably be to assert those parts that are predictable, using for example regex:

Assert.assertTrue(titleText
  .matches("(?i)disqualified because \\w+ can be claimed as dependent"));

The regex term \w+ means "a series of 1 or more word characters".

Note also how regex also lets you match case insensitively via the (?i) ignore-case flag, so avoiding the toLowerCase() call.

Or

If "close enough" really is good enough, use a Levenshtein distance test, an implementation of which you can find in Apache common-lang's StringUtils.getLevenshteinDistance() method:

Assert.assertTrue(StringUtils.getLevenshteinDistance(titleText, t) < 10);
Community
  • 1
  • 1
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Well, if you are sure this fits you, you could use Levenshtein Distance (or some other string matching score to compare the strings.

//Checks that at most 20% of the string are different using Levenshtein distance score
assertTrue(StringUtils.getLevenshteinDistance(titleText.toLowerCase(), t.toLowerCase()) < titleText.length()*0.2)
bezmax
  • 25,562
  • 10
  • 53
  • 84
1

don't use regex. regex can help you only if you know the text patterns in advance and if the patterns are relatively simple.

you have to choose a metric of similarity that best fits your needs. the most famous is Levenshtein distance (or edit distance). you can find it, for example, in apache commons. if you need something more complex, you can use fuzzy string search or even use full text search (lucene etc)

but probably you won't find any of those in assertions/matchers libraries - use dedicated tool to do the comparision

Community
  • 1
  • 1
piotrek
  • 13,982
  • 13
  • 79
  • 165