unit testing framework
This commit is contained in:
parent
d8e9bfe8bd
commit
8c091d7add
|
@ -3,7 +3,7 @@ from flask import Flask
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
from flask.ext.sqlalchemy import SQLAlchemy
|
||||||
from flask.ext.login import LoginManager
|
from flask.ext.login import LoginManager
|
||||||
from flask.ext.openid import OpenID
|
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 = Flask(__name__)
|
||||||
app.config.from_object('config')
|
app.config.from_object('config')
|
||||||
|
@ -13,5 +13,25 @@ lm.setup_app(app)
|
||||||
lm.login_view = 'login'
|
lm.login_view = 'login'
|
||||||
oid = OpenID(app, os.path.join(basedir, 'tmp'))
|
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
|
from app import views, models
|
||||||
|
|
||||||
|
|
18
app/forms.py
18
app/forms.py
|
@ -1,5 +1,6 @@
|
||||||
from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
|
from flask.ext.wtf import Form, TextField, BooleanField, TextAreaField
|
||||||
from flask.ext.wtf import Required, Length
|
from flask.ext.wtf import Required, Length
|
||||||
|
from app.models import User
|
||||||
|
|
||||||
class LoginForm(Form):
|
class LoginForm(Form):
|
||||||
openid = TextField('openid', validators = [Required()])
|
openid = TextField('openid', validators = [Required()])
|
||||||
|
@ -8,3 +9,20 @@ class LoginForm(Form):
|
||||||
class EditForm(Form):
|
class EditForm(Form):
|
||||||
nickname = TextField('nickname', validators = [Required()])
|
nickname = TextField('nickname', validators = [Required()])
|
||||||
about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)])
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,19 @@ class User(db.Model):
|
||||||
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
|
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
|
||||||
about_me = db.Column(db.String(140))
|
about_me = db.Column(db.String(140))
|
||||||
last_seen = db.Column(db.DateTime)
|
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):
|
def is_authenticated(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -8,7 +8,12 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Your nickname:</td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td>About yourself:</td>
|
<td>About yourself:</td>
|
||||||
|
|
15
app/views.py
15
app/views.py
|
@ -16,7 +16,16 @@ def before_request():
|
||||||
g.user.last_seen = datetime.utcnow()
|
g.user.last_seen = datetime.utcnow()
|
||||||
db.session.add(g.user)
|
db.session.add(g.user)
|
||||||
db.session.commit()
|
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('/')
|
||||||
@app.route('/index')
|
@app.route('/index')
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -94,7 +103,7 @@ def user(nickname):
|
||||||
@app.route('/edit', methods = ['GET', 'POST'])
|
@app.route('/edit', methods = ['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit():
|
def edit():
|
||||||
form = EditForm()
|
form = EditForm(g.user.nickname)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
g.user.nickname = form.nickname.data
|
g.user.nickname = form.nickname.data
|
||||||
g.user.about_me = form.about_me.data
|
g.user.about_me = form.about_me.data
|
||||||
|
@ -102,7 +111,7 @@ def edit():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash('Your changes have been saved.')
|
flash('Your changes have been saved.')
|
||||||
return redirect(url_for('edit'))
|
return redirect(url_for('edit'))
|
||||||
else:
|
elif request.method != "POST":
|
||||||
form.nickname.data = g.user.nickname
|
form.nickname.data = g.user.nickname
|
||||||
form.about_me.data = g.user.about_me
|
form.about_me.data = g.user.about_me
|
||||||
return render_template('edit.html',
|
return render_template('edit.html',
|
||||||
|
|
11
config.py
11
config.py
|
@ -12,4 +12,13 @@ OPENID_PROVIDERS = [
|
||||||
{ 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]
|
{ 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
|
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 = ['you@example.com']
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!flask/bin/python
|
||||||
|
from app import app
|
||||||
|
app.run(debug = False)
|
|
@ -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()
|
Loading…
Reference in New Issue