Marialena
Marialena

Reputation: 817

Store console output in a file - Python , unittest

I have a python script in which I wrote some unit tests and I am using selenium.

I want to extract the whole output of the console (not only my prints but also the unit test related results), so that I can import them later in my test management tool.

Output

Here is my code:

import unittest
from selenium import webdriver
import json
import requests
import sys


class TestUbuntuHomepage(unittest.TestCase):
    global strs

    strs = []

    def setUp(self):
        sys.stdout = open("C:\\Users\\Marialena\\Downloads\\out2.log", 'wt')

        self.driver = webdriver.Firefox(executable_path="C:\\Users\\Marialena\\Downloads\\selenium-drivers\\geckodriver")


    def testTitle(self):
        self.driver.get('http://www.ubuntu.com/')

        if self.assertIn('Ubuntu', self.driver.title):
            strs.append('test'})


    def tearDown(self):
        self.driver.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)

Using sys.stdout = open("C:\\Users\\Marialena\\Downloads\\out2.log", 'wt') I get in the file everything I have printed and I also get this exception:

Traceback (most recent call last): File "C:\Program Files\JetBrains\PyCharm\PyCharm Community Edition 2017.3.3\helpers\pycharm_jb_unittest_runner.py", line 35, in main(argv=args, module=None, testRunner=unittestpy.TeamcityTestRunner, buffer=not JB_DISABLE_BUFFERING) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\main.py", line 95, in init self.runTests() File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\main.py", line 256, in runTests self.result = testRunner.run(self.test) File "C:\Program Files\JetBrains\PyCharm\PyCharm Community Edition 2017.3.3\helpers\pycharm\teamcity\unittestpy.py", line 304, in run return super(TeamcityTestRunner, self).run(test) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\runner.py", line 176, in run test(result) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 84, in call return self.run(*args, **kwds) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 122, in run test(result) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 84, in call return self.run(*args, **kwds) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 122, in run test(result) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 84, in call return self.run(*args, **kwds) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\suite.py", line 122, in run test(result) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\case.py", line 653, in call return self.run(*args, **kwds) File "C:\Users\Marialena\AppData\Local\Programs\Python\Python36-32\Lib\unittest\case.py", line 624, in run result.stopTest(self) File "C:\Program Files\JetBrains\PyCharm\PyCharm Community Edition 2017.3.3\helpers\pycharm\teamcity\unittestpy.py", line 260, in stopTest output = sys.stdout.getvalue() AttributeError: '_io.TextIOWrapper' object has no attribute 'getvalue'

Any help with this, please? Thank you.

Upvotes: 0

Views: 2518

Answers (1)

zvone
zvone

Reputation: 19382

It looks like PyCharm is replacing sys.stdout with its own stream, so when you replace it with a file stream, PyCharm fails to use it.

So, limit your interventions to the scope of one function, to avoid interference with PyCharm.

This is the general idea:

def testTitle(self):
    original_stdout = sys.stdout
    sys.stdout = open("C:\\Users\\Marialena\\Downloads\\out2.log", 'wt')

    # your test code goes here

    sys.stdout = original_stdout

Now, from the outside, it will look like sys.stdout was never modified.

Of course, you'll want to improve on some things:

  • handle exceptions in test - restore stdout in a finally block
  • avoid deleting the file in each test - open the file in append mode
  • avoid having to copy-and-paste this code in each test - make a context manager
@contextmanager
def redirected_stdout(filename):
    original_stdout = sys.stdout
    sys.stdout = open(filename, 'at')
    try:
        yield
    finally:
        sys.stdout = original_stdout

and then:

def testTitle(self):
    with redirected_stdout("C:\\Users\\Marialena\\Downloads\\out2.log"):
        # your test code goes here

Alternatively:

Investigate how PyCharm expects sys.stdout to behave and make your own class which does both: writes to file and provides the API which PyCharm expects.

Upvotes: 1

Related Questions