Search code examples
pythontddpytest

pytest to insert caplog fixture in test method


I have the following test class for pytest:

class TestConnection(AsyncTestCase):
      '''Integration test'''

      @gen_test
      def test_connecting_to_server(self):
          '''Connecting to the TCPserver'''
          client = server = None
          try:
              sock, port = bind_unused_port()
              with NullContext():
                  server = EchoServer()
                  server.add_socket(sock)
              client = IOStream(socket.socket())

              #### HERE I WANT TO HAVE THE caplog FIXTURE

              with ExpectLog(app_log, '.*decode.*'):
                  yield client.connect(('localhost', port))
                  yield client.write(b'hello\n')
                  # yield client.read_until(b'\n')
                  yield gen.moment
                  assert False
          finally:
              if server is not None:
                  server.stop()
              if client is not None:
                  client.close()

Within this class apparently ExpectLog is not working so after a day of digging around in pytest's documentation I found that there is this caplog fixture that you can have inserted in you methods in order to access the captured logs. It seems to work if I have a test function to which I add the caplog argument but how do I make the caplog fixture available within the methods of a test class like the one above?


Solution

  • Although you can't pass fixtures as parameters to unittest test methods, you can inject them as instance attributes. Example:

    # spam.py
    import logging
    
    def eggs():
        logging.getLogger().info('bacon')
    

    Test for spam.eggs():

    # test_spam.py
    import logging
    import unittest
    import pytest
    import spam
    
    
    class SpamTest(unittest.TestCase):
    
        @pytest.fixture(autouse=True)
        def inject_fixtures(self, caplog):
            self._caplog = caplog
    
        def test_eggs(self):
            with self._caplog.at_level(logging.INFO):
                spam.eggs()
                assert self._caplog.records[0].message == 'bacon'