What is the correct way to report an error in a Python unittest in the setUp method?
Question: I've read some conflicting advice on the use of `assert` in the `setUp` method
of a Python unit test. I can't see the harm in failing a test if a
precondition that test relies on fails.

For example:

    
    
    import unittest
    
    class MyProcessor():
        """
        This is the class under test
        """
    
        def __init__(self):
            pass
    
        def ProcessData(self, content):
            return ['some','processed','data','from','content'] # Imagine this could actually pass
    
    class Test_test2(unittest.TestCase):
    
        def LoadContentFromTestFile(self):
            return None # Imagine this is actually doing something that could pass.
    
        def setUp(self):
            self.content = self.LoadContentFromTestFile()
            self.assertIsNotNone(self.content, "Failed to load test data")
            self.processor = MyProcessor()
    
        def test_ProcessData(self):
            results = self.processor.ProcessData(self.content)
            self.assertGreater(results, 0, "No results returned")
    
    if __name__ == '__main__':
        unittest.main()
    

This seems like a reasonable thing to do to me i.e. make sure the test is able
to run. When this fails because of the setup condition we get:

    
    
    F
    ======================================================================
    FAIL: test_ProcessData (__main__.Test_test2)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Projects\Experiments\test2.py", line 21, in setUp
        self.assertIsNotNone(self.content, "Failed to load test data")
    AssertionError: unexpectedly None : Failed to load test data
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    
    FAILED (failures=1)
    


Answer: The purpose of `setUp` is to reduce [Boilerplate
code](https://en.wikipedia.org/wiki/Boilerplate_code) which creates between
the tests in the test class during the Arrange phase.

In the Arrange phase you: setup everything needed for the running the tested
code. This includes any initialization of dependencies, mocks and data needed
for the test to run.

Based on the above paragraphs you should not assert anything in your `setUp`
method.

So as mentioned earlier; **If you can't create the test precondition then your
test is broken.** To avoid situations like this Roy Osherove wrote a great
book called: [The Art Of Unit
Testing](http://rads.stackoverflow.com/amzn/click/1617290890) ( For a fully
disclosure Lior Friedman(He was Roy's boss) is a friend of mine and I worked
closely with them for more then 2 years, so I am little bit biased...)

Basically there are only a few reasons to have an interaction with external
resources during the Arrange phase(or with things which may cause an
exception), most of them(if not all of them) are related in integration tests.

Back to your example; There is a pattern to structure the tests where you need
to load an external resource(for all/most of them). Just a side note; before
you decide to apply this pattern make sure that you can't has this content as
a static resource in your UT's class, if other test classes need to use this
resource extract this resource into a module.

The following pattern decrease the possibility for failure, since you have
less calls to the external resource:

    
    
    class TestClass(unittest.TestCase):
    
        def setUpClass(self):
            # since external resources such as other servers can provide a bad content
            # you can verify that the content is valid
            # then prevent from the tests to run  
            # however, in most cases you shouldn't.
            self.externalResourceContent = loadContentFromExternalResource()
    
    
        def setUp(self):
            self.content = self.copyContentForTest()
    

Pros:

  1. less chances to failure
  2. prevent inconsistency behavior (1. something/one has edited the external resource. 2. you failed to load the external resource in some of your tests)
  3. faster execution

Cons:

  1. the code is more complex

