Sunday, October 20, 2019

Starting unit testing in Python Power Electronics

My work as a web developer has introduced me to the wonders of unit testing. No one likes writing tests and neither did I for a very long time. I relied on manual testing like many others. Until I started writing unit tests in Jasmine for my web apps. The number of scenarios that you can test makes your code way more reliable.

Another advantage of testing is that quite often there are changes you would like to make but don't want to make them right now as you might break the code that is working. And in the end these changes never happen as you get too busy with other stuff. Here, test driven development can solve the problem of this inertia. Even if you do not want to change the code itself, test suites can help to totally determine every potential lapse in a block of code that will take away the fear bit by bit of finally getting around to fixing them.

With these noble thoughts, I have finally got over my laziness and decided to write tests for the circuit simulator. As a start, Python comes with the in-built unittest module for writing tests. Django uses this and creates a class TestCase to test API end points. Besides this, Python also has the pytest module that needs to be separately installed.

So, I decided to write unit tests for the command line interface with pytest and for the web app using Django's TestCase class based on unittest. In the beginning, the code for these will be separate. However, with time, the plan will be have one set of tests and also at the same time have one set of code for both web apps.

So, the directory structure for the simulator is:

README
command_line
            --  circuit_solver.py
            --  circuit_elements.py
            --  circuit_exceptions.py
            --  LICENSE.txt
            --  matrix.py
            --  network_reader.py
            --  solver.py

web_app
            -- requirements.txt
            -- simulator_interface
                     -- LICENSE.txt
                     -- manage.py
                     -- simulation_collection
                     -- media_files
                     -- simulator_interface
                                 -- settings.py
                                 -- urls.py
                                 -- wsgi.py
                     -- simulations
                                 -- circuit_solver.py
                                 -- circuit_elements.py
                                 -- circuit_exceptions.py
                                 -- solver.py
                                 -- network_reader.py
                                 -- matrix.py
                                 -- admin.py
                                 -- views.py
                                 -- models.py
                                 -- tests.py


There may be a few more directories and files, but these are the major ones at least for testing. We will create a tests directory inside command_line directory and house the command line app tests there. We will remove the tests.py file inside the simulations directory  inside web_app/simulator_interface and create a tests directory for the web app tests.

To install pytest, just do:
pip install pytest

For the command line app, I decided to get started with testing by writing a very simple test for the function csv_element_2D:



This function takes a tuple/list that represents a row, column position and converts it to a string that represents the cell position. So, [0,0] will be "1A" on a spreadsheet. So, a test for this function in the the command_line app would be:



The test itself if very simple. We import the method from the file network_reader.py that has the method. The test function has to start with test_ for pytest to execute it. The asset method in pytest merely asserts that for the test to pass, the value returned by the function for a particular argument has to be equal to a certain value.

The challenge in getting this test to run was in pytest being able to find the file/module network_reader.py. For this the first block of code above the function had to be written. I had to extract the parent method and insert it into the python path so that Python will look in that directory for the module and import it.

The test for the web app was a bit easier as I didn't have to struggle with path as much. The only challenge was I was trying to use pytest and it would not work as pytest for some reason could not find django module that is imported in the web app modules. The reason I can think of is in Django 2 onwards, the app needs to be loaded and therefore, django is not available until the app is working. For this, I had to go with the default Django TestCase class.



To run these tests. Inside command_line directory, just run the command:
pytest

There are several arguments that can be passed and I will investigate as time goes on. For the web app, inside the directory that contains manage.py, run:
python manage.py test simulations

The app name simulations is important because the tests directory with the test is inside the simulations app directory.


No comments:

Post a Comment