4

I am carrying out a Unit Test in Python, where I am trying to check if the elements within two lists are within a certain range of each other. The two lists I am considering are yields and list_of_yields and was considering doing self.assertEqual(round(yields-list_of_yields, 7), 0). However - is an unsupported type for lists, so my two issues are how to check if elements are within a certain range and how to carry out an assert on multiple elements as I've been told that having multiple asserts is bad practice. I saw this answer, but my question is slightly different.

Thank You

Community
  • 1
  • 1
user131983
  • 3,787
  • 4
  • 27
  • 42
  • 1
    What's the ordering of the elements? Say we have the following lists `[a, b, c]` and `[x, y, z]` and a closeness function that returns true like `def close(item1, item2)`. Are you wanting to check the elements only in the order in which they are indexed in the list such as: `all(( close(a,x), close(b,y), close(c, z) ))`? Or are you just looking to see if there is any permutation of choices from both lists that can satisfy the criteria? – shuttle87 Aug 18 '15 at 18:25
  • `any([ abs(x - y) > 7 for x, y in zip(yields, list_of_yields) ])`? – twalberg Aug 18 '15 at 20:59

2 Answers2

1

If the elements are to be compared in the exact order in which they appear you can create a a utility function that takes parameters and checks that they satisfy some condition:

def close_round(item1, item2, rounding_param):
    """Determines closeness for our test purposes"""
    return round(item1, rounding_param) == round(item2, rounding_param)

Then you can use this in a test case like so:

assert len(yields1) == len(list_of_yields)
index = 0
for result, expected in zip(yields, list_of_yields):
    self.assertTrue(close_round(result, expected, 7),
                    msg="Test failed: got {0} expected {1} at index {2}".format(result, expected, index))
    index+=1

You might find this type of pattern useful in which case you could create a function that does this:

def test_lists_close(self, lst1, lst2, comp_function):
    """Tests if lst1 and lst2 are equal by applying comp_function
    to every element of both lists"""
    assert len(lst1) == len(lst2)
    index = 0
    for result, expected in zip(yields, list_of_yields):
        self.assertTrue(comp_function(result, expected),
                        msg="Test failed: got {0} expected {1} at index {2}".format(result, expected, index))
        index+=1

If you used it a lot you would probably want to test this function too.

shuttle87
  • 15,466
  • 11
  • 77
  • 106
0

Here's a functional approach

assert(0 == (reduce(lambda a,b:a+b, map(lambda c:round(c[0]-c[1], 7), zip(yields, list_of_yeilds))))

Breaking that down: take the zip of yields and list_of_yields to get a list of pairs:

[(yields[0], list_of_yields[0]), (yields[1], list_of_yields[1]), ...]

Then map the function lambda c:round(c[0]-c[1], 7) over each pair to get the pairwise difference of yields and list_of_yields, rounded to 7 decimals.

[round(yields[0] - list_of_yields[0], 7), round(yields[1] - list_of_yields[1], 7), ...]

The last step is to check if any of the elements in this list are non-zero (in which case the lists aren't close enough). Just reduce with addition and check against 0 and you're done.

0 == round(yields[0] - list_of_yields[0], 7) + round(yields[1] - list_of_yields[1], 7) + ...
jwde
  • 642
  • 4
  • 13