title: Execute python script, get its print and logging output and assert unittest
body: <p><strong>Edit:</strong> Thanks @eemz for the idea to redesign the structure and use <code>from unittest.mock import patch</code>, but the problem persists.</p>
  <p>So I just recently stumbled into unittest and I have a program which I normally start like this <code>python run.py -config /path/to/config.file -y</code>. I wanted to write a simple test in a separate <code>test.py</code> file: Execute the script, pass the mentioned arguments and get all of its output. I pass a prepared config file which is missing certain things, so the <code>run.py</code> will break and exactly log this error using <code>logging.error</code>: &quot;xyz was missing in Config file!&quot; (see example below). I'll get a few words from <code>print()</code> and then the <code>logging</code> instance kicks in and handles from there on. How do I get its output so I can check it? Feel free to rewrite this, as I'm still learning, please bear with me.</p>
  <p>Simplified example:</p>
  <p><code>run.py</code></p>
  <pre class="lang-py prettyprint-override"><code>import logging
  
  def run(args):
    &lt; args.config = /path/to/config.file &gt;
    cnfg = Config(args.config)
  
    cnfg.logger.info(&quot;Let's start with the rest of the code!&quot;) # This is NOT in 'output' of the unittest
    &lt; code &gt;
  
  if __name__ == &quot;__main__&quot;:
    print(&quot;Welcome! Starting execution.&quot;) # This is in 'output' of the unittest
    &lt; code to parse arguments 'args' &gt;
    run(args)
  </code></pre>
  <p><code>Config.py</code></p>
  <pre class="lang-py prettyprint-override"><code>import logging
  
  class Config:
    def __init__(self):
      print(&quot;Creating logging instance, hold on ...&quot;) # This is in 'output' of the unittest
      logger = logging.getLogger(__name__)
      console_handler = logging.StreamHandler()
      logger.addHandler(console_handler)
      logger.info(&quot;Logging activated, let's go!&quot;) # This is NOT in 'output' of the unittest
      self.logger = logger
  
      if xyz not in config:
        self.logger.error(&quot;xyz was missing in Config file!&quot;) # This is NOT in 'output' of the unittest
        exit(1)
  </code></pre>
  <p><code>test.py</code></p>
  <pre class="lang-py prettyprint-override"><code>import unittest
  from unittest.mock import patch
  
  class TestConfigs(unittest.TestCase):
      def test_xyz(self):
          with patch('sys.stdout', new=StringIO()) as capture:
              with self.assertRaises(SystemExit) as cm:
                  run(&quot;/p/to/f/missing/xyz/f&quot;, &quot;&quot;, False, True)
          output = capture.getvalue().strip()
  
          self.assertEqual(cm.exception.code, 1)
          # Following is working, because the print messages are in output
          self.assertTrue(&quot;Welcome! Starting execution.&quot; in output)
          # Following is NOT working, because the logging messages are not in output
          self.assertTrue(&quot;xyz was missing in Config file!&quot; in output)
  
  if __name__ == &quot;__main__&quot;:
      unittest.main()
  </code></pre>