3

I'm writing code that tests via unittest if several elements exist on a certain homepage. After the test I want that the results were saved in a text file. But the results in the text file look like this:

......................
.........

------------------------------------------
Ran 12 tests in 22.562s
OK.

But i want that the output looks like this:

test_test1 (HomepageTest.HomePageTest) ... ok
test_test2 (HomepageTest.HomePageTest) ... ok
test_test3 (HomepageTest.HomePageTest) ... ok
etc....
-------------------------------------------------
Ran 12 tests in ...s
OK

This is the code I use for saving the output into a text file:

class SaveTestResults(object):
    def save(self):
       self.f = open(log_file, 'w')
       runner = unittest.TextTestRunner(self.f)
       unittest.main(testRunner = runner, defaultTest ='suite', verbosity = 2)
    
def main():
    STR = SaveTestResults()
    STR.save()

if __name__ == '__main__':
main()

What am I missing or doing wrong?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
diem_L
  • 389
  • 5
  • 22
  • I don't know this module, does the output you wish to have correspond to the output printed out to the console? – Right leg Aug 30 '17 at 09:19
  • the console print out nothing, when i remove the function **def save()** the console print out the output i want to have. But the code doesn´t save the output the way i want it – diem_L Aug 30 '17 at 09:27
  • If the console originally prints out what you're looking for, then redirecting `stdout` to a file will do the trick. Have a look at my answer, I think it should at least give you the basic idea. – Right leg Aug 30 '17 at 09:32

1 Answers1

3

If the output you wish to save in a file corresponds to what is printed out to the console, you have two main options.

1 - You're using Linux

Then just redirect the output to a file:

python script.py > output.txt

However, the output will not be printed out to the console anymore. If you want to keep the console output, use the tee unix command:

python script.py | tee output.txt

2 - You're using Windows, or you don't want to redirect the whole output to a file

You can achieve more or less the same thing using exclusively Python. You need to set the value of sys.stdout to the file descriptor where you want the output to be written.

import sys
sys.stdout = open("output.txt", 'w')

run_tests()

This will set the output stream stdout to the given file for the whole script. I would suggest defining a decorator instead:

def redirect_to_file(func):

    def decorated(*args, **kwargs):
        actualStdout = sys.stdout
        sys.stdout = open("log.txt", 'a')
        result = func(*args, **kwargs)
        sys.stdout = actualStdout

        return result

    return decorated

Then, just decorate the functions whose you want to write the output to a file:

@redirect_to_file
def run_test():
    ...

If you want a similar behaviour to tee, have a look at this post. The idea is to define a Tee class that holds the two desired streams:

class Tee:
    def __init__(self, stream1, stream2):
        self.stream1 = stream1
        self.stream2 = stream2

    def write(self, data):
        self.stream1.write(data)
        self.stream2.write(data)

    def close(self):
        self.stream1.close()
        self.stream2.close()

Then, set sys.stdout to a Tee instance whose one of the stream is the actual stdout:

tee = Tee(sys.stdout, open("output.txt", 'w'))
sys.stdout = tee

Don't forget to close the tee instance at the end of your script; else, the data written to output.txt will not be saved:

tee.close()
Right leg
  • 16,080
  • 7
  • 48
  • 81
  • tried it, but unfortunatly the output is still the same, i´m using windows and work on cloud9 – diem_L Aug 30 '17 at 09:45
  • @diem_L What did you try exactly? You said that the `save` method was preventing any output to the console. You need to restore the console output as desired before implementing any of the methods I proposed to you. – Right leg Aug 30 '17 at 09:47