Python unit tests

Today’s activity is really interesting, we have to do some practice with python unit testing. According to the official unittest documentation, it’s very similar to JUnit, so we should have no problem understanding it.

Now, here is a picture of me using hypothesis to do annotations on an old web page that we are able to see thanks to Wayback Machine.

hypothesisEvidence

While playing a little bit with Wayback Machine I found an old version of Steam’s page, the popular PC gaming platform, back in 2002. Its interesting to see that web pages were not that colorful or filled with images, this design was simple but worked really well.

oldsteam

For the next part, we have to see this Unit Testing and Test Driven Development in Python course where we will learn to set up virtual environments and unit tests using Pytest. For the exercises we are going to use PyCharm, a Python IDE that will make easier for us to run tests.

evidencepytest

The tutorial was fun and explained very well the basic functionalities that Pytest has. The activities were helpful summarize all the material and I felt that they were easy to do and understand.  Overall, Pytest is a very simple but powerful testing framework for Python, it’s really easy to use and has a lot of functionalities that solve testing problems like mocking objects and exceptions catch. It’s easy to setup as well, thanks to PyCharm I had no trouble at all when I was implementing my first tests. All the time I felt like I was using JUnit but with different syntax. At the end, Richard Wells also explained some TDD good practices, and one that called my attention was to run tests in random order, I hadn’t thought that it’s important to make sure that tests should run in any order which means that they don’t have any dependencies between each other. For other specific testing processes like coverage tools, advanced mocking or linting there are other libraries or modules that work very well with Pytest.

Chapter 4 activity

For this post we are going to show how we solved the exercises for chapter 4 using TDD. We need to add new operations like multiplying and division for the Calc.java file. The test file only has a test for the add operation as it is the only function we have in the class.

testcalc1

First of all, we need to write simple tests that describe what our new operations do. Of course, these tests should fail as we haven’t coded the functions yet.

testcalc2

Now we can start writing the functionality now, we are going to start with the subtraction as it is the first test we should pass to move to the next one. On this exercise the order we decide to write the new functions does not matter, but in more complex projects we should have a specific order to write the new functions because some tests might have multiple dependencies.

testcalc3

The next step is to write the test for the divide function. Here we have a problem, we don’t know how to implement this function because it can return a double or an integer. To follow the TDD correctly first we have to make the test pass, right now the test only ask for an integer so we will write just the code to make that correct.

testcalc4

At last, the multiply function. Here again we ask ourselves if this function should be capable of accepting float values, but it is not specified on our tests so by now we will handle only integers for the input and output.

testcalc5

 

Now lets imagine some guys from testing added new tests, now with more specific cases trying to find faults in our code. They included a test that divides two integers but the result is non integer, a test for a division by zero,  and a test with negative integers. After running the tests this happens:

testcalc6

As we can notice, only the division function is not passing the new tests. On one test it is expecting float numbers, on the other test, it is expecting us to catch an error when the divisor is zero. This means that we need a refactor to return doubles and to detect divisions by zero. This will change some of our previous tests, the first division test is working but it is expecting integers, the new test is expecting  doubles, there is an inconsistency in the tests and we should define this with the team first. The final decision is that a division should return doubles because it gives a more exact result. With that information we can go back to the tests, modify them accordingly and now start working on the refactor.

testcalc7

With this exercise we practiced TDD and refactoring. We learned how important it is to have good tests that defines the requirements for each function and that show how specific behavior should be handled. Also, it showed us how in TDD the tests are the guideline of our code and that it can show design errors or inconsistencies before we start writing the code, a huge advantage over other methodologies.

The code of the exercise is available here:

Calc.java

CalcTest.java