duncan-r / SHIP

Simple Hydraulic model Interface for Python
MIT License
7 stars 6 forks source link

Update tests to pass on linux #4

Closed JamesRamm closed 7 years ago

JamesRamm commented 7 years ago

This PR updates the tests to pass on linux. I have not been able to check these tests are still ok on windows yet, so this would need double checking first.

It consists of 3 main changes:

Hopefully this is a first small step toward ensuring x platform support.

JamesRamm commented 7 years ago

Just a note to say; travis is failing because of the integration tests (which this PR does not address), the log shows the unit tests to be passing now.

duncan-r commented 7 years ago

Thanks @JamesRamm

I've had a look through this and it's causing some issues when running the tests on windows. The failures are to do with the difference between the the way that PathHolder stores the path variables and the way that the new utils.fakeAbsPath() converts the path. I.e. the path holder converts to os format, but the fakeAbsPath doesn't convert absolute paths, only non-absolute paths. E.g.

===================================================================
FAIL: test_absolutePath (tests.test_filetools.PathHolderTests)
Test that the absolute path is returned correctly.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\users\duncan\documents\program\python\ship\tests\test_filetools.py", line 67, in test_absolutePath
    self.assertEqual(self.fake_abs_path, abs_path, 'absolutePath() fail')
AssertionError: 'c:/first/second/third/fourth/TuflowFile.txt' != 'c:\\first\\second\\third\\fourth\\TuflowFile.txt'
- c:/first/second/third/fourth/TuflowFile.txt
?   ^     ^      ^     ^      ^
+ c:\first\second\third\fourth\TuflowFile.txt
?   ^     ^      ^     ^      ^
 : absolutePath() fail

I think this one can probably be solved by ensuring that the utils function updates the absolute path, in the same manner as the other check. E.g.

def fakeAbsPath(path):
    '''
    Make a pretend filepath 'absolute' for the current os.
    Will massage absolute paths for the wrong OS to abs paths
    for current os
    '''
    if os.path.isabs(path):
        # --> Do the same replace here  <--
        if os.name == 'posix':
            newpath = path.replace('\\', os.sep)
        else:
            newpath = path.replace('/', os.sep)
    elif os.name == 'posix':
        # We may have been given a windows path, so remove the drive and
        # make it root dir
        newpath = path.replace('c:', '').replace('\\', os.sep)
        if not newpath.startswith('/'):
            newpath = '/{}'.format(newpath)
    else:
        newpath = 'c:{}{}'.format(os.sep, path)

    return newpath

We're also having the same issues with the relative paths. So another function in utils for handling that will be needed to:

def fakeRelPath(path):
    if os.name == 'posix':
        newpath = path.replace('\\', os.sep)
    else:
        newpath = path.replace('/', os.sep)

    return newpath

Which can used in the same way: fakeRelPath('../fifth')

I realise that this is all a bit tricky for you to check on a linux env, so I'm happy to pull it down, make the changes and get it merged in if you want?

However, I think this all points to a bit of an issue in the way the PathHolder class stores the path information. I think perhaps that we need to consider checking what the os is at the start of the load, storing that and handling the way paths are stored and updated based on that the whole way through. We should probably also consider whether to allow the user to set what type of paths they would like to use when writing out the files. It may be that you run it on linux, but want to write paths out as windows, or visa-versa (which could be achieved by setting the root variable. Also, tuflow doesn't care whether you use forward or back slashes in relative paths, but the user may have a preference. So we should probably allow that preference. I will have a bit of a think about this.

Don't worry about the integration tests. They're pretty rough, so I'm happy to make sure that they're setup properly and everything is passing once this work is complete. I'm thinking it might be a good idea to create a 'pathfixes' branch or something to do all of this on?

Let me know if you have any thoughts.

duncan-r commented 7 years ago

I've had a bit of a think about this and have some ideas:

JamesRamm commented 7 years ago

With the exception of setFinalFolder I don't think PathHolder/filetools.py would cause any x-platform issues as it is pretty much using standard lib functions. There are a couple of functions which seem to be to get around using is_file or is_dir in order to cater for fake path?

One solution to fix the tests would be:

In reply to your points above - In general, I think it would be safe to assume that the machine SHIP is being run on is the same machine that tuflow would be run on? In which case we should always throw errors for badly formatted paths. We can then simply safely use standard library functions without worrying about the OS (with the exception of the setFinalFolder function, which can be changed to use os functions anyway). I think it would be a more unusual situation for a user to want to run SHIP on linux but then tuflow on windows or vice versa. Even if that did occur; they obviously have access to the other machine so can easily run whatever SHIP stuff they need to do on the same machine (or at least a machine with same OS). Then we can also easily write in validation checks for the file being read in (i.e. do those files actually exist).

I think a truly robust solution will require changes to both filetools and the unit tests. It is generally more common to have small test data (for a relevant example see the gdal tests) or generate files on the fly for unit tests than use fake paths. We probably want (should) expect SHIP to fail if paths dont exist / are malformed on the current OS.

A problem then for generating files and then passing the relative path is that it needs to be relative to something. Tuflow expects all paths to be relative to the tcf file. Essentially, to properly handle relative paths in PathHolder, it needs to know what it is relative to. I.e I think PathHolder needs some knowledge of the absolute path to the TCF file.

JamesRamm commented 7 years ago

PS; it is probably a good idea to move this discussion to an issue...