Is there a way to have a doctest with file paths as output that will succeed regardless of the OS it's run on?
For example, on Windows this will work:
r"""
>>> import foo
>>> relative_path = foo.getRelativePath()
>>> print relative_path
'bar\\foobar'
"""
if __name__ == '__main__':
from doctest import testmod
print testmod()
But of course will fail on Linux and produce an error similar to:
Failed example:
print relative_path
Expected:
'bar\\foobar'
Got:
'bar/foobar'
How can I make the above work on any OS?
EDIT
I know I can do something like this instead:
>>> relative_path == os.path.join('bar', 'foobar')
True
But I'm wondering if there is a different and better way to do this.
Clarification
Doctests are alluring because of their simplicity, but it's a misleading simplicity. You expect the test line to represent an expression that doctest will evaluate against the result of the last expression, but it's not; it's actually just doing a simple, basic string comparison.
#doctesttest.py
"""
>>> "test"
"test"
python -m doctest doctesttest.py
Gives
...
Expected:
"test"
Got:
'test'
Although - in pythonic terms - "test" == 'test'
, even "test" is 'test'
, str(""" 'test' """)
does not match str(""" "test" """)
.
Armed with this awareness...
Solution
The following will fail on all systems:
def unique_paths(path_list):
""" Returns a list of normalized-unique paths based on path_list
>>> unique_paths(["first/path", ".\\first/path", "second/path"])
['first/path', 'second/path']
"""
return set(os.path.normpath(p) for p in path_list)
We're looking for a simple string match, so we need to look for an easily matchable result string. You don't care about the separator, so either eliminate it or replace it, or test around it:
def unique_paths(path_list):
""" Returns a list of normalized-unique paths based on path_list
>>> paths = unique_paths(["first/path", ".\\\\first/path", "second/path"])
>>> len(paths)
2
>>> [os.path.split(path) for path in sorted(list(paths))]
[('first', 'path'), ('second', 'path')]
# or heck, even
>>> sorted(list(paths[0])).replace('\\\\', '/')
'first/path'
"""
return set(os.path.normpath(p) for p in path_list)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With