Orange Wheel: Backend with Flask. Trying out pytest.

Set up Directories & Environments:

To separate out an environment for my backend as well, the first thing I did was:

  • At the root directory of the project, used command mkdir backend to create a directory for backend.
  • Did cd backend to enter to the backend directory.
  • Did pip -m venv venv, which was what Python 3 use to create virtual environment. Python2 should be virtualenv venv. This project would be Python 3.
  • Invoked the virtual environment with . venv/bin/activate. It should work without problem. To deactivate the environment, just use the command deactivate.

Now for the framework.

I chosen Flask for this project, which I installed with pip install Flask. The reason was that backend shouldn’t be too complicated for this project, so a micro-framework known was ideal. There would be fetch call for the external membership website, a scraper to process the data, and maybe some storage to save user preferences.

Trying out Testing in Python:

Since I set up frontend testing, of course I would do backend. I hadn’t done testing in Python framework before though. Since pytest was what the Flask team had in their documentation on test, let’s go with that!

To get test coverage, I also installed pytest-cov. Together, the command was pip install pytest pytest-cov. From now on, if I want to run a test while also view code coverage, I just have to run pytest –cov=src.

I created a very basic scraper/app.py, with an index() that returned a string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask


def create_app():
  app = Flask(__name__)

  @app.route('/')
  def index():
    return 'flask index page'

  return app


if __name__=='__main__':
  app = create_app()
  app.run(port=5000)

I then created a test directory with a test_basic.py to test for the string, but that’s not the only file I have to create. I also had to create what was named a conftest.py in the test directory. The pytest automatically discovers conftest.py, which is a file used to share fixture function. I am bit confuse on what fixture function is, but it seems to be a pytest feature that setup and teardown resources in a modular manner. The returned fixture objects are automatically passed into test functions as input arguments? I could be wrong though. If anyone can explain it well, please comment below!

Anyway, the test/test_basic.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
import pytest
from scraper.app import create_app

@pytest.fixture
def client(app):
    #create a test client for app
    return app.test_client()

@pytest.fixture
def app():
    app = create_app()
    app.debug = True
    return app

This creates the client fixture, which is pass as an argument in the test/test_basic.py:

1
2
3
4
5
6
7
8
9
import pytest
from flask import url_for

class TestLanding:
  def test_landing_page(self, client):
    response = client.get('/')
    print(response.data)
    assert response.status_code == 200
    assert response.data.decode('UTF-8') == 'flask index page'

The data in the returned response is actually in byte, so the test failed because the we are asserting against a string. I had seen tutorials where the solution was to do a assert text in response.data, but I prefer a more precise and less hack-y solution. I ended up doing assert response.data.decode(‘UTF-8’) == text.

So now I have a very basic test setup for both frontend and backend. Next up, setting up basic look of the app with Vue!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.