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