f-log

just another web log

03 Oct 2020:
flog life kitchen and functional skills
There is a lot going on at the moment. Kitchen is being re-done and we have had no freezer for the last couple of weeks. Things are starting to get back together, but still surviving on mainly take-aways.

I am also awaiting the tests results of my functional skills. I did really badly at school and now I have to prove I can complete at a basic level.

Not to mention I messed up the img tag in the last post and the only way to fix it is with a another post to update it :)
03 Oct 2020:
if you need a unittest output colorised you have to do it yourself
So I there I was running my Python3 unit tests and the the count got up to 200 tests across 7 modules. The unit tests executed quickly and I "could" interpret the output and track down issues when they occurred...

With that many tests and modules the output was not eye catchingly formatted and I found myself wishing I could colourise the output. Just a simple GREEN for passes and RED for failures...

It turns out this has bugged many a developer. Unfortunately there are 101 ways to to resolve the problem and all of them involve install extra software. In some cases you have to replace the unittest module completely and follow the new testing modules rules and requirements.

I did not find this a very satisfactory conclusion, so I wrote my own bash script to solve it.


#!/bin/bash
# Run all the test_*.py unit tests and colourise the output

clear=$(tput op)
green=$(tput setaf 10)
red=$(tput setaf 9)
find . -iname "test_*.py" -printf 'pushd "%h";python3 "%f" 2>&1| sed -re \
"s/FAILED/'$red'FAILED'$clear'/" -e \
"s/^(F+)[.]?$|[.](F+)|(F+)[.]/'$red'F'$clear'/g" -e \
"s/OK/'$green'OK'$clear'/";popd> /dev/null\n' | bash


and the output looks like this

python3 unittest output colourised

very readable at a glance!

The tput commands create the correct ANSI escape sequences. Manually inputting them did not go well.

The script then finds all the files starting with test_ and ending with .py and then constructs a command sequence as a string.

These are then piped in to a new bash shell.

Replacing the strings for FAILED and OK so that they are RED and GREEN respectively was easy. Tying to cover all cases where the F in the .... dots needed to be RED was a lot more difficult.
regex for the F characters explained

FYI the pushd popd commands handle tests in sub directories.
03 Oct 2020:
unit test your unit tests with unittest
I have been doing a lot of Python at work the last few months and I feel the need to teach everyone about the power of unit tests.

Unit tests can confirm that a program will work correctly - logically. You just need to create at least one test for each possible path in the code. Then, when you refactor, running the tests will prove the logic still executes correctly.

import unittest
import myproject

# test some things!
class test_things(unittest.TestCase):

    result = None
    real = None

    def setUp(self):
        self.real = myproject.check


    def tearDown(self):
        myproject.check = self.real


    def check_Mock(self, row):
        return self.result


    def test_check_positive(self):
        self.result = True
        myproject.check = self.check_Mock
        value = "Good value"
        result = myproject.check(value)
        self.assertTrue(result)

if __name__ == '__main__':
    unittest.main(buffer=True)
    unittest.main()


In this example we are unit testing the check method in the myproject module. It is a bad example, but you do not want to see the boring real world stuff I was doing.

You need to include the Python builtin module unittest and the code module you want to test with import statements.

Create a new class and derive from unittest.TestCase, add a method prefixed with test_ that uses an assert method.

To run the test/s you call unittest.main()

and then execute the file as you would any other Python3 .py file.

python3 test_myproject.py

or target a specific test

python3 test_myproject.py test_things.test_check_positive

The result will detail where any asserts failed and how many tests passed. More details on unittest output in the next post.

As you can see from the above code there is a lot of other bits and pieces you can do.

if __name__ == '__main__':

Makes sure this code is not run if it is imported as a module in another Python file. Good practice and if it is missing can cause unexpected mayhem. I.e when you import your module that is missing this line into the unittest, your code will execute before the test.

unittest.main(buffer=True)

Stops your code under test output from messing up the test results output. Sometimes it makes sense to leave this out, but in my experience you really need it as the default. Especially when you have hundreds of tests.

Then we have the setUp and tearDown methods that are run at the start and end of every test respectively. It is essential that anything a test needs to run is undone before the next test, as tests are not guaranteed to be run in order.

My example makes a "backup" of the check method before the test overwrites it with a "Mock" method. The example does not make a lot sense here, but imaging the "Mock" was a database class and contained mock methods for everything the program was going to do with the database.

There are lots of assert methods, but you will mostly use assertTrue and assertEquals.

Tests should never take long to execute, so you can run the tests regularly with zero impact.

One key side affect of unit testing is finding yourself wanting to make methods simpler to make testing simpler. That is very good thing!

In my next post I will share a bash script that runs all the test files recursively and colourises the output.
loading results, please wait loading animateloading animateloading animate
[More tags]
rss feed

email

root

flog archives


Disclaimer: This page is by me for me, if you are not me then please be aware of the following
I am not responsible for anything that works or does not work including files and pages made available at www.jumpstation.co.uk I am also not responsible for any information(or what you or others do with it) available at www.jumpstation.co.uk In fact I'm not responsible for anything ever, so there!