Testing filters

muir-woods-mossy-fernsSo every once in a while I stumble upon an instance of this problem:

  1. I have a list of entities of type A
  2. I want to filter out some of the entities, with a predicate P returning a boolean for each A-instance a in the list

I try to test the predicate by building some ”positives” and some ”negatives”. But often I get the nagging feeling either the positives or the negatives form such a huge space of possibilities, that it becomes a pain to create instances of even a small subset of the variations.

For example, if I have some base-type/interface Base and the elements of the list are subtypes of this type, S1, S2, …, SN and the filter is supposed to let through only elements of type S1 and S2 but not Sk, k>=3. Also instances of S1 and S2 have to have some certain properties fullfilling some criteria to pass. You can imagine the combinatorial explosion of instances I have to try out in the test code, even to test a subset of all possibilities.

Add to that that some of the Si subtypes have 2 or 3 constructor parameters, and we’re in the jungle.

My current approach is

”test one to three positives, and one to three negatives. Ignore the nagging feeling”.

How do you approach this example?


Taggar: , , ,

8 Responses to Testing filters

  1. Olof skriver:

    Hi Helen;

    Hmm. Yeah I haven’t tried out pex, mostly because I do test-first development. So having a tool generate test cases for me feels … awkward.

    What is your experience with Pex? Do you use it extensively or as a complement to TDD/test-first development? Pros/cons?

  2. Osias skriver:

    Theses days I had to write an SQL query and tested that way:

    1 or 2 positives – always appear in query result
    one negative for each condition on ”where” clase, I mean one negative that ”almost” positive.

    I’m sure if I am explaining it well, let me invent an example:

    I wish to bring a list of Brazilian state capitals with more than 400 years old and more than 10 million inhabitants. Only São Paulo must comes.

    I insert: (entirely made up figures)

    City name | isCapital | city age | inhabitants
    São Paulo | true | 450 | 11000000
    Rio | true | 410 | 9000000
    Campinas | false | 490 | 10500000
    Vitória | true | 300 | 11000000

    You see, Rio, Campinas and Vitória ”almost” appear, each one with a failing condition. Is there a better way, I suppose.

  3. Osias skriver:

    I mean ”there is better way”

  4. Osias skriver:

    I mean “there is A better way”. I suck at typing today.

  5. Olof skriver:

    @Osias:

    Thanks for you input. Basically, that’s the way I do it too. Try a few positives, and a few negatives. Then trust the method to do alright.

    I got some feedback on a mailing list too, about more thorough methods — eg. splitting the ”filter function” into two different functions, and testing them separately. One that tests the ”type correctness” and one that tests each type-specific filter behaviour. Then I can be reasonably sure the composition of the two ”atom filters” work alright (if I trust the composition operator, which I can test separately also).

    Thanks again, my fingers slip often too, no worries 🙂

  6. Osias skriver:

    Well, I tried to follow that discussion on TDD list, but I am lost when they start to talk about some patterns I never saw.

  7. Olof skriver:

    Yeah I was lost there too – especially the really long and technical post that I tried to explain above. Been thinking about it quite a lot since that, and even though I don’t follow every single step of the way, I think the general idea of ”divide and conquer” is a good one, the composition idea that is.

Lämna en kommentar