Skip to content

Commit

Permalink
unit testing framework
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Dec 17, 2012
1 parent d8e9bfe commit 8c091d7
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 7 deletions.
22 changes: 21 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
from flask.ext.openid import OpenID
from config import basedir
from config import basedir, ADMINS, MAIL_SERVER, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD

app = Flask(__name__)
app.config.from_object('config')
Expand All @@ -13,5 +13,25 @@
lm.login_view = 'login'
oid = OpenID(app, os.path.join(basedir, 'tmp'))

if not app.debug:
import logging
from logging.handlers import SMTPHandler
credentials = None
if MAIL_USERNAME or MAIL_PASSWORD:
credentials = (MAIL_USERNAME, MAIL_PASSWORD)
mail_handler = SMTPHandler((MAIL_SERVER, MAIL_PORT), 'no-reply@' + MAIL_SERVER, ADMINS, 'microblog failure', credentials)
mail_handler.setLevel(logging.ERROR)
app.logger.addHandler(mail_handler)

if not app.debug:
import logging
from logging.handlers import RotatingFileHandler
file_handler = RotatingFileHandler('tmp/microblog.log', 'a', 1 * 1024 * 1024, 10)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('microblog startup')

from app import views, models

18 changes: 18 additions & 0 deletions app/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
from flask.ext.wtf import Required, Length
from app.models import User

class LoginForm(Form):
openid = TextField('openid', validators = [Required()])
Expand All @@ -8,3 +9,20 @@ class LoginForm(Form):
class EditForm(Form):
nickname = TextField('nickname', validators = [Required()])
about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])

def __init__(self, original_nickname, *args, **kwargs):
Form.__init__(self, *args, **kwargs)
self.original_nickname = original_nickname

def validate(self):
if not Form.validate(self):
return False
if self.nickname.data == self.original_nickname:
return True
user = User.query.filter_by(nickname = self.nickname.data).first()
if user != None:
self.nickname.errors.append('This nickname is already in use. Please choose another one.')
return False
return True


14 changes: 13 additions & 1 deletion app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,19 @@ class User(db.Model):
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
about_me = db.Column(db.String(140))
last_seen = db.Column(db.DateTime)


@staticmethod
def make_unique_nickname(nickname):
if User.query.filter_by(nickname = nickname).first() == None:
return nickname
version = 2
while True:
new_nickname = nickname + str(version)
if User.query.filter_by(nickname = new_nickname).first() == None:
break
version += 1
return new_nickname

def is_authenticated(self):
return True

Expand Down
7 changes: 7 additions & 0 deletions app/templates/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<h1>File Not Found</h1>
<p><a href="{{url_for('index')}}">Back</a></p>
{% endblock %}
8 changes: 8 additions & 0 deletions app/templates/500.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<h1>An unexpected error has occurred</h1>
<p>The administrator has been notified. Sorry for the inconvenience!</p>
<p><a href="{{url_for('index')}}">Back</a></p>
{% endblock %}
7 changes: 6 additions & 1 deletion app/templates/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ <h1>Edit Your Profile</h1>
<table>
<tr>
<td>Your nickname:</td>
<td>{{form.nickname(size = 24)}}</td>
<td>
{{form.nickname(size = 24)}}
{% for error in form.errors.nickname %}
<br><span style="color: red;">[{{error}}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td>About yourself:</td>
Expand Down
15 changes: 12 additions & 3 deletions app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ def before_request():
g.user.last_seen = datetime.utcnow()
db.session.add(g.user)
db.session.commit()


@app.errorhandler(404)
def internal_error(error):
return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return render_template('500.html'), 500

@app.route('/')
@app.route('/index')
@login_required
Expand Down Expand Up @@ -94,15 +103,15 @@ def user(nickname):
@app.route('/edit', methods = ['GET', 'POST'])
@login_required
def edit():
form = EditForm()
form = EditForm(g.user.nickname)
if form.validate_on_submit():
g.user.nickname = form.nickname.data
g.user.about_me = form.about_me.data
db.session.add(g.user)
db.session.commit()
flash('Your changes have been saved.')
return redirect(url_for('edit'))
else:
elif request.method != "POST":
form.nickname.data = g.user.nickname
form.about_me.data = g.user.about_me
return render_template('edit.html',
Expand Down
11 changes: 10 additions & 1 deletion config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@
{ 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')

# mail server settings
MAIL_SERVER = 'localhost'
MAIL_PORT = 25
MAIL_USERNAME = None
MAIL_PASSWORD = None

# administrator list
ADMINS = ['[email protected]']
3 changes: 3 additions & 0 deletions runp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!flask/bin/python
from app import app
app.run(debug = False)
42 changes: 42 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!flask/bin/python
import os
import unittest

from config import basedir
from app import app, db
from app.models import User

class TestCase(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.config['CSRF_ENABLED'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')
db.create_all()

def tearDown(self):
db.drop_all()

def test_avatar(self):
# create a user
u = User(nickname = 'john', email = '[email protected]')
avatar = u.avatar(128)
expected = 'http://www.gravatar.com/avatar/d4c74594d841139328695756648b6bd6'
assert avatar[0:len(expected)] == expected

def test_make_unique_nickname(self):
# create a user and write it to the database
u = User(nickname = 'john', email = '[email protected]')
db.session.add(u)
db.session.commit()
nickname = User.make_unique_nickname('john')
assert nickname != 'john'
# make another user with the new nickname
u = User(nickname = nickname, email = '[email protected]')
db.session.add(u)
db.session.commit()
nickname2 = User.make_unique_nickname('john')
assert nickname2 != 'john'
assert nickname2 != nickname

if __name__ == '__main__':
unittest.main()

0 comments on commit 8c091d7

Please sign in to comment.