Exceptions may be raised in a few places in the Tasks API. Let’s take a quick peek at the functions found in tasks/api.py:
| def add(task): # type: (Task) -> int |
| def get(task_id): # type: (int) -> Task |
| def list_tasks(owner=None): # type: (str|None) -> list of Task |
| def count(): # type: (None) -> int |
| def update(task_id, task): # type: (int, Task) -> None |
| def delete(task_id): # type: (int) -> None |
| def delete_all(): # type: () -> None |
| def unique_id(): # type: () -> int |
| def start_tasks_db(db_path, db_type): # type: (str, str) -> None |
| def stop_tasks_db(): # type: () -> None |
There’s an agreement between the CLI code in cli.py and the API code in api.py as to what types will be sent to the API functions. These API calls are a place where I’d expect exceptions to be raised if the type is wrong.
To make sure these functions raise exceptions if called incorrectly, let’s use the wrong type in a test function to intentionally cause TypeError exceptions, and use with pytest.raises(<expected exception>), like this:
| import pytest |
| import tasks |
| |
| |
| def test_add_raises(): |
| """add() should raise an exception with wrong type param.""" |
| with pytest.raises(TypeError): |
| tasks.add(task='not a Task object') |
In test_add_raises(), the with pytest.raises(TypeError): statement says that whatever is in the next block of code should raise a TypeError exception. If no exception is raised, the test fails. If the test raises a different exception, it fails.
We just checked for the type of exception in test_add_raises(). You can also check the parameters to the exception. For start_tasks_db(db_path, db_type), not only does db_type need to be a string, it really has to be either ’tiny’ or ’mongo’. You can check to make sure the exception message is correct by adding as excinfo:
| def test_start_tasks_db_raises(): |
| """Make sure unsupported db raises an exception.""" |
| with pytest.raises(ValueError) as excinfo: |
| tasks.start_tasks_db('some/great/path', 'mysql') |
| exception_msg = excinfo.value.args[0] |
| assert exception_msg == "db_type must be a 'tiny' or 'mongo'" |
This allows us to look at the exception more closely. The variable name you put after as (excinfo in this case) is filled with information about the exception, and is of type ExceptionInfo.
In our case, we want to make sure the first (and only) parameter to the exception matches a string.