18

Hello I am new to programming and and trying to make a test that checks whether any items in a list of items are present in another list (using unittest in Python 2.7).

For example if I have a list ["dog", "cat", "frog] and the result of the method I am testing is ["tiger", "lion", "kangaroo", "frog] I want the test to fail because it contains one of the items of the previous list ("frog"). I would also like the test to tell me what words did both lists have (i.e. what words caused the test to be a fail).

I have tried:

self.assertIn(["cat", "dog"], method("cat dog tiger"))

The result of the method is ["cat", "dog", "tiger"] yet the result of the test is a fail and says:

AssertionError: ['cat', 'dog'] not found in ['cat', 'dog', 'tiger']

I want this test to return ok because 'cat' and 'dog' are present in the second list. It seems assertIn doesn't do what I thought it would do (I thought it was to check if any of a are present in b).

And vice versa, assertNotIn passes when I want it to fail.

I've been searching for a while now but because I'm not sure what I'm looking for which makes it hard to find.

Thank you for reading, I hope that makes sense.

EDIT: I have gone with Chris's solution and it works as I want:

def myComp(list1, list2):
    section = list(set(list1).intersection(list2))

To get the list of words that overlap (i.e. triggering the fail) in the error message, I added the code below from here How to change the message in a Python AssertionError?:

try:
    assert(len(section)==0)
except AssertionError as e:
    e.args += ('The following are present in the processed text', 
    section)
    raise

The result is exactly what I want:

AssertionError: ('The following are pressent in the processed text', ['dog', 
'cat'])
RubyJane
  • 185
  • 1
  • 1
  • 6
  • the list `['cat', 'dog']` is not found in the list `['cat', 'dog', 'tiger']` try `print ['a'] in ['a']` in a prompt - it's false because the list is not in the list, and it doesn't do an element-wise comparison. – Stael Aug 17 '17 at 13:37

4 Answers4

18

You can either iterate through your list and assertIn, or use sets and you could do something like self.assertTrue(set(a).issuperset(set(b))).

Alex
  • 1,432
  • 14
  • 26
8

You should have a look at this question, then you can easily see that something like:

def myComp(list1, list2):
  section = list(set(list1).intersection(list2))
  return ((len(section)==0), section)

this function will return a tuple with a boolean indicating failing or success and the list of items occurring in both lists.

if you really want to do this in an assert statement you could just use the first element of that tuple...

Chris
  • 710
  • 7
  • 15
  • 1
    Thanks Chris that worked exactly as I want. I do want to keep the assert statement but also wanted to have a list of what caused the fail. Searching Stack overflow I found a post about changing the assert error statement which I added to the end of your code, I hope it is ok programming practice as it does exactly what I need!: try: assert(len(section)==0) except AssertionError as e: e.args += ('The following are pressent in the processed text', section) raise – RubyJane Aug 17 '17 at 14:57
5
self.assertTrue(any(animal in method("cat dog tiger") for animal in ("cat", "dog")))
2

If you're expecting non-repeatable values in your sequences, maybe it's better to consider using sets, cause you can easily check them for any kind of overlapping.

>>> a, b = {'dog', 'cat'}, {'dog', 'cat', 'wolf', 'crab'}
>>> a & b
set(['dog', 'cat'])
>>> a ^ b
set(['wolf', 'crab'])

So checking for a being subset of b would be something like this:

>>> not bool(a ^ b & a)
True

etc

Violet Red
  • 211
  • 1
  • 4