unit testing framework

This commit is contained in:
Miguel Grinberg 2012-12-16 00:32:38 -08:00
parent d8e9bfe8bd
commit 8c091d7add
10 changed files with 140 additions and 7 deletions

View File

@ -3,7 +3,7 @@ from flask import Flask
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')
@ -13,5 +13,25 @@ lm.setup_app(app)
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

View File

@ -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()])
@ -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

View File

@ -13,6 +13,18 @@ class User(db.Model):
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

7
app/templates/404.html Normal file
View File

@ -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
app/templates/500.html Normal file
View File

@ -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 %}

View File

@ -8,7 +8,12 @@
<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>

View File

@ -17,6 +17,15 @@ def before_request():
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
@ -94,7 +103,7 @@ 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
@ -102,7 +111,7 @@ def edit():
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',

View File

@ -13,3 +13,12 @@ OPENID_PROVIDERS = [
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
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 = ['you@example.com']

3
runp.py Executable file
View File

@ -0,0 +1,3 @@
#!flask/bin/python
from app import app
app.run(debug = False)

42
tests.py Executable file
View File

@ -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 = 'john@example.com')
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 = 'john@example.com')
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 = 'susan@example.com')
db.session.add(u)
db.session.commit()
nickname2 = User.make_unique_nickname('john')
assert nickname2 != 'john'
assert nickname2 != nickname
if __name__ == '__main__':
unittest.main()