Unittesting CODESYS python scripts

2016-10-13
2023-08-17
  • DavidCozens - 2016-10-13

    Please forgive my if this is obvious, I'm not a python expert. I have some scripts that work inside CODESYS, but I need to extend them and I want them to be maintainable, so I want to introduce a Unittest framework around the modules before refactoring and then adding more code.

    I want my unit tests to be fast so that I can use TDD, so I don't want to work inside CODESYS. Instead I want to work using activepython and to be able to use the features of mock and mock.patch to replace the CODESYS API calls. But I haven't yet managed to get this to work.

    As an example I have created a cutdown example using a couple of very simple files
    Vendor.py

    class Vendor(object):
        def __init__(self, name):
            self.name = name
    

    TestVendor.py

    import mock
    import unittest
    import Vendor
    class TestVendor(unittest.TestCase):
        
        def testName(self):
            vendor = Vendor.Vendor('VendorName')
            self.assertEqual('VendorName', vendor.name)
            
    if __name__ == "__main__":
        #import sys;sys.argv = ['', 'Test.testName']
        unittest.main()
    

    This simple test runs and passes.

    I want to add some functionality that uses the librarymanager, the first test that I want is to verify that there is a single call to , when I create a Vendor object. One of my many attempts starts like this, I've just tried to declare the module I am mocking, no actual test.

        @mock.patch('librarymanager')
        def testGetAllLibrariesCalled(self):
            '''
            '''
     
    

    I get the following error when I try to run the test

    Zitat:
    TypeError: Need a valid target to patch. You supplied: 'librarymanager'

    How would I write this first test? i.e. mock the module, mock the function, and assert that the function is called. I'm sure if I can get this first call tested the rest will be straightforward.

    If I'm going down the wrong track, and I would be better trying this unit testing using different tools then please let me know.

     
  • DavidCozens - 2016-10-14

    I've managed to solve this myself. Rather than battering my head trying to work out how to mock a global like librarymanager, I have created a class to wrap the codesys interface, and used dependency injection to pass this to my script. I can then create a mock using mock.create_autospec(CodesysInterface). A much nicer solution...

     

Log in to post a comment.