Testing in Python with Pytest
Tags: python, testing, beginners
Published: 2020-06-19 20:58:06

I'm taking a bit of a different approach with my blog posts this week, I've decided to talk a little bit about testing in Python with PyTest.

I never learned how to write unit tests before and as I was discovering what they're all about I thought I'd share a bit with all of you.

###What is unit testing and what are unit tests?
Unit testing and unit tests are function based tests that enable developers to verify individual modules (functions, classes, etc.) at the lowest level. 

These tests are done to ensure that the particular module is working as it was designed to. Usually sample data is used in unit tests so that the module can be tested without needing to test all other parts of the program.

As opposed to integration testing, where the program is run as a whole, unit testing allows for each part of the program to be checked for functionality. This way, in theory, the entire program should run smoothly if each part of the program is ensured to run correctly.

###Implementation using PyTest
There are many different testing programs out there but I decided to use PyTest because it's very simple and easy to understand, in addition to being widely used.

For PyTest to work, we will need to first install PyTest:

```python
pip install pytest
```

After installing, we will need to make a test folder inside the app that we are currently working on. This test folder will be able to hold all of the files we will write our tests in. In our case we'll be testing some lists and classes. I want to test a file called lists.py inside of my projects app, so we'll create a file inside of our tests folder called test_lists.py. If you wanted to do this on the command line it would look something like this:

```python
mkdir tests
cd tests
touch test_lists.py
```
Note about file names: For every testing file you make, you will take the existing file name with your written code and prepend the file name with test_. That is why in our case we made test_lists.py, and in this file is where all of our testing scripts will be written.

Our actual lists.py file looks like this:
```python
class Projects:
    def __init__(self):
        self.storage = []

    def __len__(self):
        return len(self.storage)
```

We have initialized our class Projects and created a few functions just to create the internal storage for our class which can hold different data structures.

For our test file we will need to import the file that contains the data that we would like to test. Our tests folder is being held inside of the projects folder that contains our lists.py file. The folder structure would look something like this:

![Breakdown of file structure](https://dev-to-uploads.s3.amazonaws.com/i/152aim958pcb9q387dwa.png)

So the importing line would look like this given the above file structure:

```python
import projects.lists import Projects
```

If we wanted to write a test to confirm that an instance of our project class is exactly that, we could write something like this:

```python
def test_constructor():
  a = Projects()
  assert isinstance(a, Projects)
  assert len(a) == 0
```
Assert is short for assertion and is the information provided that you want to test is made true by your module. Here we put in isinstance to confirm that a is an instance of the class Project.

We are also testing for our len function which confirms that the current length of the instance is 0.

Now to give the test a try, we'll go to our terminal and type in

```python
python -m pytest -v
```

This will run tests for all of the files that are located in our directory. After running it for that particular example we get back:

```python
=========================================================================================================== test session starts ===========================================================================================================
platform darwin -- Python 3.8.2, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- /Users/Megan/Projects/django-portfolio/.env/bin/python
cachedir: .pytest_cache
rootdir: /Users/Megan/Projects/django-portfolio/portfolio
collected 1 item                                                                                                                                                                                                                          

projects/tests/test_lists.py::test_constructor PASSED                                                                                                                                                                               [100%]

============================================================================================================ 1 passed in 0.05s ==========================================================================================================
```

We can see from here that our test passed! And indeed a is an instance of the class Projects with a length of 0.

###Benefits of Testing
There are many advantages to testing, but just to name a few:
 - To make sure the code your writing actually works!
 - Confirm that code will be mostly bug free when put into production or given to a client
 - Makes for a better development process, ensuring quality as you go along instead of just having a huge program built with tons of bugs that doesn't work
 - Allows for good documentation so your whole team is aware of what more needs to be developed or not

This is just a simple example to give you an idea of how unit tests can be written. I've included some resources below that can further your knowledge and understanding of testing in Python.

###Resources
Here are a few helpful resources that I used to help myself understand unit testing better:
- [Test-Driven Development with PyTest](https://realpython.com/courses/test-driven-development-pytest/)
- [Basic Unit Testing in Python](https://docs.python-guide.org/writing/tests/)


Thanks again for taking the time to read my article on tests. I hope that this could be helpful for you the next time you decide you want to write tests in Python.