Learn Test Driven Development in Flask - Part 1

Firstly, a caveat  for this article:  Writing this is part of my own process in learning how to TDD a flask app, I haven't done more than just play with the framework until this point and am in no way an expert.  The lack of decent information out there on how to do this is stagering, so hopefully my documenting this learning process will help others starting out.

Secondly, while this is supposed to be about TDD, this first article has no tests what-so-ever! There is a reason for that however, this is the very basic of basic Flask, getting the basic layout in place. Part 2 will jump into Users & Authentication -- with tests! or so is my hope.  Comments, suggestions, and contributions are welcome.  The Git repo can be found at https://github.com/wsimmerson/BasicBlog

And now to get started...

Create project folder:

  • mkdir BasicBlog
  • cd BasicBlog
 
Create Environment: If you are new to virtualenv, or have never used it, you should! Check out http://docs.python-guide.org/en/latest/dev/virtualenvs/ for details.
  • virtualenv ENV --no-site-packages
 
Create basic file layout:
  • mkdir app
  • mkdir app/static
  • mkdir app/static/css
  • mkdir app/static/js
  • mkdir app/templates
  • mkdir tests
  • touch run.py
  • touch config.py
  • touch app/__init__.py
  • touch app/templates/404.html
 
Switch to the virtual env:
  • source ENV/bin/activate
You will see a (ENV) at the front of your prompt now
 
Install Flask packages that we will need.
  • pip install flask flask-sqlalchemy flask-wtf
  • pip freeze > requirements.txt
 
vim run.py
from app import app
app.run(host='0.0.0.0', port=8080, debug=True)

 
vim config.py
DEBUG = True

##
# Define application directory
##
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

##
# Define the database configuration (SQlite3)
##
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'basicblog.db')
DATABASE_CONNECT_OPTIONS = {}

##
# Application threads
##
THREADS_PER_PAGE = 2

##
# Security stuff
##
CSRF_ENABLED = True
CSRF_SESSION_KEY = "And now for something completely different"
SECRET_KEY = "Thou Shalt Not Pass!!!" 
 
vim app/__init__.py
 ##
# Handle Imports
##
from flask import Flask, render_template
from flask.ext.sqlalchemy import SQLAlchemy

##
# Set up the App
##
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)

##
# Basic HTTP error handling
@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

##
# Import and Register Blueprints
##

# We will do this later ;)

##
# Create the database
##
db.create_all()
 
Now we will start working on a page to display.
 
First download the blueprint framework from blueprintcss.org and extract the blueprint directory to app/static/css/blueprint, it will help us get started without looking too crappy.
 
vim app/templates/layout.html
 <!DOCTYPE html>
<html>
  <head>
    <title>BasicBlog</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/blueprint/screen.css') }}" media="screen">
    <link rel="stylesheet" href="{{ url_for('static', filename='css/blueprint/print.css') }}" media="print">
  </head>

  <body>

    <header>
      <div class="container">
        <h1 class="logo">BasicBlog</h1>
    </header>

    <div class="container">
      {% with messages = get_flashed_messages(with_categories = True) %}
        {% if messages %}
          <div class="flashes">
            <ul>
              {% for category, message in messages %}
                <div class='{{  category  }}'>{{ message }} </div>
              {% endfor %}
            </ul>
          </div>
        {% endif %}
      {% endwith %}

      {% block content %}

      {% endblock %}
    </div>

  </body>
</html> 
 
vim app/templates/404.html
 
{% extends "layout.html" %}

{% block content %}

  <h2>ERROR!</h2>
  <p>404 Page not found!</p>

{% endblock %}
 
At this point we can now run the app successfully, but since we havent defined any controllers/routes its just going to give us our 404 error page.
 

BasicBlog


ERROR!

404 Page not found!

 
Now would be a good time to set up version control.
 
vi .gitignore
ENV/
tmp/
__pycache__
*.db
*.swp
*.pyc
 
git init
git add .
git commit -am "first commit"
 
# Optional - create repository on GitHub
git remote add origin git@github.com:your_user_name/BasicBlog.git
git push -u origin master