I'm trying to write a unittest that will redirect stdout and stderr to a file written on a Windows network drive. For some reason, the same script (only diff. is the directory path) works on Linux but not on Windows. When run on Windows, nothing is written to the log file.
Here is the script on Windows and nothing gets written:
import sys
import unittest
LOGDIR = r"\\windows\somenetwork\somedrive"
LOG1 = open(LOGDIR+'\myStdOut.txt', 'w')
LOG2 = open(LOGDIR+'\myStdErr.txt', 'w')
class MyTest(unittest.TestCase):
currentResult = None # holds last result object passed to run method
def setUp(self):
pass
def tearDown(self):
ok = self.currentResult.wasSuccessful()
errors = self.currentResult.errors
failures = self.currentResult.failures
print ' All tests passed so far!' if ok else \
' %d errors and %d failures so far' % \
(len(errors), len(failures))
def run(self, result=None):
self.currentResult = result # remember result for use in tearDown
unittest.TestCase.run(self, result) # call superclass run method
def test_onePlusOneEqualsTwo(self):
self.assertTrue(1 + 1 == 2) # succeeds
def test_onePlusOneEqualsThree(self):
self.assertTrue(1 + 1 == 3) # fails
def test_onePlusNoneIsNone(self):
self.assertTrue(1 + None is None) # raises TypeError
if __name__ == '__main__':
sys.stdout = LOG1
sys.stderr = LOG2
unittest.main()
LOG1.close()
LOG2.close()
The same script run on Linux works or would at least write to the files:
import sys
import unittest
LOGDIR = r"/tmp"
LOG1 = open(LOGDIR+'/myStdOut.txt', 'w')
LOG2 = open(LOGDIR+'/myStdErr.txt', 'w')
class MyTestLinux(unittest.TestCase):
currentResult = None # holds last result object passed to run method
def setUp(self):
pass
def tearDown(self):
ok = self.currentResult.wasSuccessful()
errors = self.currentResult.errors
failures = self.currentResult.failures
print ' All tests passed so far!' if ok else \
' %d errors and %d failures so far' % \
(len(errors), len(failures))
def run(self, result=None):
self.currentResult = result # remember result for use in tearDown
unittest.TestCase.run(self, result) # call superclass run method
def test_onePlusOneEqualsTwo(self):
self.assertTrue(1 + 1 == 2) # succeeds
def test_onePlusOneEqualsThree(self):
self.assertTrue(1 + 1 == 3) # fails
def test_onePlusNoneIsNone(self):
self.assertTrue(1 + None is None) # raises TypeError
if __name__ == '__main__':
sys.stdout = LOG1
sys.stderr = LOG2
unittest.main()
LOG1.close()
LOG2.close()
This may not be the best way to do this, but it works (at least on my machine):
Running this produces:
stdout.txt
stderr.txt
os.dup(fd)
The
os.dupfunction creates a copy of the file descriptor and returns the integer of that duplicated file descriptor. So, after the first twodupcalls, there are two file descriptors pointing tostdoutand two pointing tostderr.os.dup2(fd, fd2)
The
os.dup2function copies the file descriptor fromfdtofd2and closes the file descriptor offd2. So, after thedup2calls,stdoutnow points to theffile descriptor and likewisestderrnow points to thegfile descriptor (and becausedup2closes the second file descriptor, there is only a single file descriptor for bothstdoutandstderrbecause of the copies made by the call todup).Print everything to your heart's content.
At the end, the last two
dup2calls revert the file descriptors using the copied file descriptors (so stdout and stderr point to where you'd expect) which also closes filesfandg.According to the dup2 docs, this works on both Linux and Windows.
[Edit]
If it's not too much work, I would suggest not using prints and use
logginginstead: