total rewrite

This commit is contained in:
Oleg Pidsadnyi 2013-11-10 12:52:14 +01:00
parent d375fb2542
commit 0ab9c440de
69 changed files with 340 additions and 10277 deletions

View File

@ -1,8 +0,0 @@
language: python
python:
- "2.6"
- "2.7"
# command to install dependencies
install: "python setup.py develop"
# command to run tests
script: python setup.py test

View File

@ -1,4 +0,0 @@
pytest-bdd-example
==================
Example application and the tests using the pytest-bdd

4
README.rst Normal file
View File

@ -0,0 +1,4 @@
pytest-bdd-example
==================
Example application and the tests using the pytest-bdd

View File

@ -1,18 +0,0 @@
Scenario: Successful login
Given I'm an admin user
When I go to the admin login page
And I fill in the login credentials
And I post the form
Then I shouldn't see an error message
And I should see the Dashboard page
Scenario: Unsuccessful login
When I go to the admin login page
And I fill in wrong login credentials
And I post the form
Then I should see an error message

View File

@ -0,0 +1,32 @@
Scenario: Successful login
Given I'm not logged in
When I go to login page
And I enter "admin" username
And I enter "default" password
And I click login button
Then I should see "You were logged in"
Scenario: Invalid username
Given I'm not logged in
When I go to login page
And I enter "wrong" username
And I enter "default" password
And I click login button
Then I should see "Error: Invalid username"
Scenario: Invalid password
Given I'm not logged in
When I go to login page
And I enter "wrong" username
And I enter "default" password
And I click login button
Then I should see "Error: Invalid username"

View File

@ -0,0 +1,21 @@
Scenario: Entry is displayed
Given I have an entry
When I go to the blog
Then I should see my entry
Scenario: No form for visitors
Given I'm a visitor
When I go to the blog
Then I shouldn't see an entry form
Scenario: Create an entry
Given I'm an admin
When I go to the blog
And I enter entry title
And I enter entry text
And I click the Share button
Then I should see "New entry was successfully posted"
And I should see the entry title
And I should see the entry text

View File

@ -1,33 +0,0 @@
#!/usr/bin/env python
from flask.ext.script import Manager, Shell, Server
from pytest_bdd_example import dashboard
from pytest_bdd_example import shop
def create_app(app=None):
APPS = {
'dashboard': dashboard.app,
'shop': shop.app,
}
return APPS[app]
manager = Manager(create_app)
manager.add_option('-app', '--application', dest='app', required=True)
manager.add_command('runserver', Server('127.0.0.1'))
manager.add_command('shell', Shell(use_ipython=True))
@manager.command
def mkdb():
from tests.helpers.mkdb.db import recreate_database
from tests.helpers.mkdb.initialdata import create_initial_data
recreate_database()
create_initial_data()
if __name__ == '__main__':
manager.run()

View File

@ -1,6 +0,0 @@
from .decorators import public_endpoint
from .blueprint import auth
from .security import user_datastore
__all__ = ['auth', 'public_endpoint', 'user_datastore']

View File

@ -1,21 +0,0 @@
from flask import Blueprint
from flask.ext.security import Security
from .manager import login_manager, check_valid_login
from .security import user_datastore
from .forms import LoginForm
auth = Blueprint('auth', __name__, template_folder='../')
@auth.record_once
def on_registered(state):
state.app.config['SECURITY_LOGIN_USER_TEMPLATE'] = 'auth/login.html'
Security(
state.app,
user_datastore,
login_form=LoginForm,
)
login_manager.init_app(state.app)
state.app.before_request(check_valid_login)

View File

@ -1,3 +0,0 @@
def public_endpoint(function):
function.is_public = True
return function

View File

@ -1,47 +0,0 @@
from flask.ext.wtf import Form
from wtforms import TextField, PasswordField, BooleanField
from wtforms.validators import Required
from flask.ext.security.forms import NextFormMixin
from flask.ext.security.utils import verify_and_update_password, get_message
from flask.ext.security.confirmable import requires_confirmation
from .security import user_datastore
class LoginForm(Form, NextFormMixin):
username = TextField('Username', [Required()])
password = PasswordField('Password', [Required()])
remember = BooleanField('Remember me')
def validate(self):
if not super(LoginForm, self).validate():
return False
username = self.username.data.strip()
password = self.password.data.strip()
if username == '':
self.username.errors.append(get_message('EMAIL_NOT_PROVIDED')[0])
return False
if password == '':
self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
return False
self.user = user_datastore.find_user(username=username)
if self.user is None:
self.username.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
return False
if not verify_and_update_password(password, self.user):
self.password.errors.append(get_message('INVALID_PASSWORD')[0])
return False
if requires_confirmation(self.user):
self.username.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
return False
if not self.user.is_active():
self.username.errors.append(get_message('DISABLED_ACCOUNT')[0])
return False
return True

View File

@ -1,31 +0,0 @@
from flask import request, current_app
from flask.ext.login import LoginManager, current_user
from .security import user_datastore
login_manager = LoginManager()
login_manager.login_view = 'security.login'
PUBLIC_ENDPOINTS = [
'static',
'security.login',
]
def check_valid_login():
if request.endpoint in PUBLIC_ENDPOINTS:
return
if getattr(current_app.view_functions.get(request.endpoint), 'is_public', False):
return
if not current_user.is_authenticated():
return current_app.login_manager.unauthorized()
@login_manager.user_loader
def load_user(userid):
return user_datastore.find_user(id=userid)

View File

@ -1,42 +0,0 @@
from flask import current_app
from flask.ext.security import UserMixin, RoleMixin
db = current_app.extensions['sqlalchemy'].db
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True)
email = db.Column(db.String(120), unique=True)
password = db.Column(db.String(20))
active = db.Column(db.Boolean, default=False)
roles = db.relationship(
Role,
secondary=lambda: roles_users,
backref=db.backref('users', lazy='dynamic'),
)
def get_id(self):
return unicode(self.id)
def is_active(self):
return self.active
def is_anonymous(self):
return False
roles_users = db.Table(
'roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey(User.id)),
db.Column('role_id', db.Integer(), db.ForeignKey(Role.id)),
)

View File

@ -1,4 +0,0 @@
from flask.ext.security import SQLAlchemyUserDatastore
from .models import db, User, Role
user_datastore = SQLAlchemyUserDatastore(db, User, Role)

View File

@ -1,5 +0,0 @@
from .models import db, Author, Book
from .blueprint import book
__all__ = ['book', 'db', 'Author', 'Book']

View File

@ -1,45 +0,0 @@
from flask import current_app
from flask.ext.admin.contrib.sqlamodel import ModelView
from flask.ext.principal import Permission, RoleNeed
from pytest_bdd_example.book import db, Book, Author
admin = current_app.extensions['admin'][0]
admin_role = Permission(RoleNeed('admin'))
class AuthorView(ModelView):
"""Author view.
Only admin can see it.
"""
def is_visible(self):
return admin_role.can()
def is_accessible(self):
return admin_role.can()
admin.add_view(
AuthorView(
Author,
db.session,
'authors',
endpoint='authors',
)
)
admin.add_view(
ModelView(
Book,
db.session,
'books',
endpoint='books',
)
)

View File

@ -1,7 +0,0 @@
from flask import Blueprint
from .admin import admin
book = Blueprint('book', __name__)
__all__ = ['book', 'admin']

View File

@ -1,32 +0,0 @@
from flask import current_app
db = current_app.extensions['sqlalchemy'].db
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(30))
last_name = db.Column(db.String(30))
sur_name = db.Column(db.String(30))
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50))
description = db.Column(db.Text)
authors = db.relationship(
Author,
secondary=lambda: author_books,
backref='books',
order_by=Author.id,
)
author_books = db.Table(
'author_books',
db.Column('author_id', db.Integer, db.ForeignKey(Author.id)),
db.Column('book_id', db.Integer, db.ForeignKey(Book.id)),
)

View File

@ -1,4 +0,0 @@
from .app import app
__all__ = ['app']

View File

@ -1,14 +0,0 @@
from flask.ext.admin import Admin
from flask.ext.admin.base import MenuLink
admin = Admin(
name='Dashboard',
url='/',
)
admin.add_link(
MenuLink(
name='Logout',
endpoint='security.logout',
)
)

View File

@ -1,29 +0,0 @@
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from pytest_bdd_example.dashboard import settings
from .admin import admin
app = Flask(
__name__,
static_folder=settings.MEDIA_ROOT,
template_folder=settings.TEMPLATES_ROOT,
)
app.config.from_object('pytest_bdd_example.dashboard.settings')
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
admin.init_app(app)
db = SQLAlchemy(app)
with app.app_context():
from pytest_bdd_example.auth import auth
from pytest_bdd_example.book import book
app.register_blueprint(auth, url_prefix='/auth')
app.register_blueprint(book)
# Register the views
from .views import *

View File

@ -1,8 +0,0 @@
import os
DEBUG = True
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
MEDIA_ROOT = os.path.join(BASE_PATH, '../media')
TEMPLATES_ROOT = os.path.join(BASE_PATH, '../templates', 'dashboard')
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_PATH, '../dashboard.db')

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +0,0 @@
body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}

File diff suppressed because one or more lines are too long

View File

@ -1,10 +0,0 @@
from flask import Flask
from .settings import TEMPLATES_ROOT, MEDIA_ROOT
app = Flask(
__name__,
template_folder=TEMPLATES_ROOT,
static_folder=MEDIA_ROOT,
)

View File

@ -1,9 +0,0 @@
import os
DEBUG = True
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
MEDIA_ROOT = os.path.join(BASE_PATH, 'media')
TEMPLATES_ROOT = os.path.join(BASE_PATH, 'templates', 'shop')
SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/pytestbdd-example.db'

View File

@ -1,60 +0,0 @@
{% extends "base.html" %}
{% block extra_head %}
<style type="text/css">
.form-signin {
max-width: 300px;
padding: 19px 29px 29px;
margin: 0 auto 20px;
background-color: #fff;
border: 1px solid #e5e5e5;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin input[type="text"],
.form-signin input[type="password"] {
font-size: 16px;
height: auto;
margin-bottom: 15px;
padding: 7px 9px;
}
</style>
{% endblock %}
{% block menu %}{% endblock %}
{% block content %}
<form class="form-signin" method='POST'>
{{ login_user_form.csrf_token }}
<h2 class="form-signin-heading">Please sign in</h2>
<div class="control-group">
<div class="controls">
{{ login_user_form.username(placeholder=login_user_form.username.label.text, class="input-block-level") }}
{% for error in login_user_form.username.errors %}<div class="alert alert-error">{{ error|e }}</div>{% endfor %}
</div>
</div>
<div class="control-group">
<div class="controls">
{{ login_user_form.password(placeholder=login_user_form.password.label.text, class="input-block-level") }}
{% for error in login_user_form.password.errors %}<div class="alert alert-error">{{ error|e }}</div>{% endfor %}
</div>
</div>
<button class="btn btn-large btn-primary" type="submit">Sign in</button>
</form>
{% endblock %}

View File

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Shop - {% block title %}Dashboard{% endblock %}</title>
<link href="{{ url_for("static", filename="bootstrap/css/bootstrap.css") }}" rel="stylesheet">
<link href="{{ url_for("static", filename="dashboard/dashboard.css") }}" rel="stylesheet">
<script type="text/javascript" src="{{ url_for("static", filename="libs/jquery-1.10.1.min.js") }}"></script>
<script src="{{ url_for("static", filename="bootstrap/js/bootstrap.min.js") }}"></script>
{% block extra_head %}{% endblock %}
</head>
<body>
{% block menu %}
<div id="form" class="modal hide" role="dialog" tabindex="-1" aria-labelledby="modal-title"></div>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="/">Dashboard</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href=".">Home</a></li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert">
<button type="button" class="close" data-dismiss="alert">&times;</button>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
</html>

View File

@ -1,7 +0,0 @@
{% extends "base.html" %}
{% block menu %}
{% endblock %}
{% block content %}
{% endblock %}

View File

@ -1,39 +1,63 @@
#!/usr/bin/env python
import os
import sys
from setuptools import setup
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand
class PyTest(TestCommand):
version = '0.0.1'
class Tox(TestCommand):
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_args = ['--recreate']
self.test_suite = True
def run_tests(self):
import pytest
errno = pytest.main(self.test_args)
#import here, cause outside the eggs aren't loaded
import tox
errno = tox.cmdline(self.test_args)
sys.exit(errno)
dirname = os.path.dirname(__file__)
long_description = (
open(os.path.join(dirname, 'README.rst')).read() + '\n' +
open(os.path.join(dirname, 'CHANGES.rst')).read()
)
setup(
name='pytest-bdd-example',
description='pytest-bdd example application',
description='PyTest BDD example',
long_description=long_description,
author='Oleg Pidsadnyi',
license='MIT license',
author_email='oleg.podsadny@gmail.com',
version='0.1',
cmdclass={'test': PyTest},
url='https://github.com/olegpidsadnyi/pytest-bdd-example',
version=version,
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS :: MacOS X',
'Topic :: Software Development :: Testing',
'Topic :: Software Development :: Libraries',
'Topic :: Utilities',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3'
] + [('Programming Language :: Python :: %s' % x) for x in '2.6 2.7 3.0 3.1 3.2 3.3'.split()],
cmdclass={'test': Tox},
install_requires=[
'flask-admin',
'flask-script',
'flask-login',
'flask-security',
'flask-sqlalchemy',
],
tests_require=[
'pytest',
'flask',
'pytest-bdd',
'pytest-bdd-splinter',
],
packages=['pytest_bdd_example'],
tests_require=['tox'],
package_dir={'': 'src'},
packages=['flaskr'],
)

View File

@ -0,0 +1,3 @@
from fixtures.app import *
from fixtures.db import *
from fixtures.entry import *

View File

@ -1 +0,0 @@
This should contain fixtures that are used in both functional and unit tests

9
tests/fixtures/app.py vendored Normal file
View File

@ -0,0 +1,9 @@
import pytest
from flaskr import flaskr
@pytest.fixture
def app():
"""Flask application."""
return flaskr.app

View File

@ -1,45 +0,0 @@
import pytest
from pytest_bdd_example.auth.models import db
from pytest_bdd_example.auth import user_datastore
from tests.helpers.random import random_string
@pytest.fixture
def password():
return 'asdasd'
@pytest.fixture
def user(password):
"""Dashboard user."""
u = user_datastore.create_user(
username=u'{0}'.format(random_string()),
email="{0}@example.com".format(random_string(7)),
password=password,
active=True,
)
db.session.commit()
return u
@pytest.fixture
def admin_user(user):
admin_role = user_datastore.find_or_create_role(
name='admin',
description='Administrators',
)
user_datastore.add_role_to_user(user, admin_role)
db.session.commit()
@pytest.fixture
def author_user(user):
author_role = user_datastore.find_or_create_role(
name='author',
description='Book authors',
)
user_datastore.add_role_to_user(user, author_role)
db.session.commit()

9
tests/fixtures/db.py vendored Normal file
View File

@ -0,0 +1,9 @@
import pytest
from flaskr import flaskr
@pytest.fixture
def db():
"""Database connection."""
return flaskr.connect_db()

22
tests/fixtures/entry.py vendored Normal file
View File

@ -0,0 +1,22 @@
import pytest
import datetime
@pytest.fixture
def title():
return "Entry for {0}".format(datetime.datetime.now())
@pytest.fixture
def text():
"""Entry text."""
return "Hello world text!"
@pytest.fixture
def entry(db, title, text):
"""Blog entry."""
db.execute('insert into entries (title, text) values (?, ?)', [title, text])
db.commit()
return title, text

View File

@ -1,15 +1,23 @@
import os
import pytest
import pytest_bdd_example as main_pkg
from tests.fixtures.auth import *
from .fixtures.browser import *
from .fixtures.auth import *
from .fixtures.steps import *
# @pytest.fixture(scope='session')
# def pytestbdd_selenium_speed():
# return 0.5
@pytest.fixture
def pytestbdd_feature_base_dir():
"""Feature files base directory."""
return os.path.join(
os.path.dirname(
os.path.dirname(main_pkg.__file__)
), 'features',
return os.path.abspath(
os.path.join(
os.path.dirname(os.path.dirname(__file__)),
'..',
'features',
)
)

View File

@ -1,54 +0,0 @@
import pytest
import splinter
from pytest_bdd import scenario, when, then
test_successful_login = scenario(
'auth/dashboard_login.feature',
'Successful login',
)
@when('I go to the admin login page')
def go_to_login_page(browser):
browser.visit('http://127.0.0.1:5000/login')
@when('I fill in the login credentials')
def fill_in_login_credentials(browser, user, password):
browser.fill('username', user.username)
browser.fill('password', password)
@when('I post the form')
def post_the_form(browser):
browser.find_by_css('button[type=submit]').first.click()
@then('I should see an error message')
def should_see_error_message(browser):
assert browser.find_by_css('.alert-error').first
@then('I shouldn\'t see an error message')
def shouldnt_see_error_message(browser):
with pytest.raises(splinter.exceptions.ElementDoesNotExist):
browser.find_by_css('.alert-error').first
@then('I should see the Dashboard page')
def should_see_dashboard(browser):
assert not browser.is_text_present('Please sign in')
test_unsuccessful_login = scenario(
'auth/dashboard_login.feature',
'Unsuccessful login',
)
@when('I fill in wrong login credentials')
def fill_in_wrong_credentials(browser):
browser.fill('username', 'HELP!')
browser.fill('password', 'I pressed any key')

View File

@ -1,8 +0,0 @@
from pytest_bdd_example.dashboard import app
from .steps.given import *
with app.app_context():
"""Initialize the application context."""
pass

View File

@ -1,5 +0,0 @@
from pytest_bdd import given
given('I\'m an admin user', fixture='admin_user')
given('I\'m an author user', fixture='author_user')

View File

@ -0,0 +1,52 @@
from pytest_bdd import scenario, when, then
test_entry_is_displayed = scenario(
"entry/entry.feature",
"Entry is displayed",
)
test_no_form_for_visitors = scenario(
"entry/entry.feature",
"No form for visitors",
)
test_create_entry = scenario(
"entry/entry.feature",
"Create an entry",
)
@then("I should see my entry")
def should_see_entry(browser, title):
assert browser.is_text_present(title)
@then("I shouldn't see an entry form")
def shoudnt_see_entry_form(browser):
assert not browser.find_by_css(".add-entry")
@when("I enter entry title")
def enter_entry_title(browser, title):
browser.fill('title', title)
@when("I enter entry text")
def enter_entry_text(browser, text):
browser.fill('text', text)
@when("I click the Share button")
def click_share_button(browser):
button = browser.find_by_css("input[type=submit]").first
button.click()
@then("I should see the entry title")
def should_see_entry_title(browser, title):
assert browser.is_text_present(title)
@then("I should see the entry text")
def should_see_entry_text(browser, text):
assert browser.is_text_present(text)

View File

@ -0,0 +1,11 @@
import pytest
@pytest.fixture
def credentials():
"""Login credentials."""
return {
'username': 'admin',
'password': 'default',
'login': True,
}

View File

@ -0,0 +1,22 @@
from urlparse import urljoin
import pytest
@pytest.fixture
def base_url():
return "http://127.0.0.1:5000/"
@pytest.fixture
def browser(browser, base_url, credentials):
if credentials["login"]:
browser.visit(urljoin(base_url, "/login"))
browser.fill("username", credentials["username"])
browser.fill("password", credentials["password"])
button = browser.find_by_css("input[type=submit]").first
button.click()
else:
browser.visit(base_url)
return browser

View File

@ -0,0 +1,36 @@
"""Common steps."""
import re
from urlparse import urljoin
from pytest_bdd import given, when, then
@then(re.compile('I should see "(?P<text>.+)"'))
def i_should_see(browser, text):
assert browser.is_text_present(text)
@given("I'm not logged in")
@given("I'm a visitor") # Step alias
def not_logged_in(credentials):
"""99%% of the cases you test logged in.
Specify not logged in state to be explicit.
"""
credentials['login'] = False
@given("I'm an admin")
def logged_in(credentials):
credentials['login'] = True
# Re-use of the fixture
given("I have an entry", fixture="entry")
@when("I go to the blog")
def go_to_blog(browser):
browser.visit(urljoin(browser.url, "/"))

View File

@ -0,0 +1,41 @@
import re
from urlparse import urljoin
from pytest_bdd import given, when, scenario
test_sucsessful_login = scenario(
"auth/login.feature",
"Successful login",
)
test_invalid_username = scenario(
"auth/login.feature",
"Invalid username",
)
test_ivalid_password = scenario(
"auth/login.feature",
"Invalid password",
)
@when("I go to login page")
def go_to_login_page(browser):
browser.visit(urljoin(browser.url, "/login"))
@when(re.compile('I enter "(?P<username>\w+)" username'))
def enter_username(browser, username):
browser.fill("username", username)
@when(re.compile('I enter "(?P<password>\w+)" password'))
def enter_password(browser, password):
browser.fill("password", password)
@when('I click login button')
def click_login(browser):
button = browser.find_by_css("input[type=submit]").first
button.click()

View File

@ -1,8 +0,0 @@
from flask import current_app
def recreate_database():
db = current_app.extensions['sqlalchemy'].db
print 'Recreating database: %s' % db.engine.url.database
db.drop_all()
db.create_all()

View File

@ -1,38 +0,0 @@
from flask import current_app
from pytest_bdd_example.auth import user_datastore
def create_initial_data():
print 'Populating the initial data...'
db = current_app.extensions['sqlalchemy'].db
print 'Creating roles...'
admin_role = user_datastore.find_or_create_role(
name='admin',
description='Administrators',
)
author_role = user_datastore.find_or_create_role(
name='author',
description='Book authors',
)
print 'Admin user: admin/asdasd'
admin = user_datastore.create_user(
username='admin',
password='asdasd',
active=True,
)
user_datastore.add_role_to_user(admin, admin_role)
print 'Author user: author/asdasd'
author = user_datastore.create_user(
username='author',
password='asdasd',
active=True,
)
user_datastore.add_role_to_user(author, author_role)
#TODO: add other data here...
db.session.commit()

View File

@ -1,10 +0,0 @@
from __future__ import absolute_import
import random
import string
def random_string(length=20):
"""Create a random string."""
alphanums = string.ascii_lowercase + string.digits
return ''.join(random.choice(alphanums) for _ in xrange(length))

24
tests/unit/test_entry.py Normal file
View File

@ -0,0 +1,24 @@
import pytest
def count_o(value):
"""Count occurences of the 'o' in a string."""
return value.count('o')
@pytest.mark.parametrize(
('title', 'o_count'),
(
('Hello', 1),
('World', 1),
('Hello World', 2),
)
)
def test_count_o(entry, o_count):
"""Test count_o counts 'o' in the string.
:note: entry depends on the title fixture.
"""
title, text = entry
assert count_o(title) == o_count