Skip to content

Commit f15da45

Browse files
committed
initial test configuration
1 parent 283870b commit f15da45

11 files changed

+269
-7
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,7 @@ constants_override.py
5454
static/.webassets-cache
5555
static/gen
5656

57+
#pytest
58+
.pytest_cache
59+
app/test_project.db
60+
app.log

.travis.yml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
language: python
2+
python:
3+
- "2.7"
4+
script:
5+
- pytest
6+
addons:
7+
postgresql: "9.4"
8+
services:
9+
- redis-server

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ open http://127.0.0.1:5000/
4747

4848
**Problems?** Hit us up in the `engineering` channel on [Discord](https://www.originprotocol.com/discord) if you need help.
4949

50+
## Run the Tests
51+
52+
53+
Throughout the development process and before committing or deploying, run:
54+
55+
```bash
56+
pytest
57+
```
58+
59+
Run individual test files simply as:
60+
61+
```bash
62+
pytest path/to/test.py
63+
```
64+
65+
Run a single test case, or an individual test, using:
66+
67+
```bash
68+
pytest path/to/test.py::test_case_name
69+
```
70+
71+
5072
## Localization
5173
See [translations](translations) directory.
5274

pytest.ini

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[pytest]
2+
env =
3+
HOST = testhost.com
4+
HTTPS = False
5+
FLASK_SECRET_KEY=test-secret-key
6+
REDIS_URL=redis://localhost:6379/0
7+
SENDGRID_API_KEY = test-sendgrid-key

requirements.txt

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ click==6.7
1111
cryptography==2.1.4
1212
decorator==4.2.1
1313
enum34==1.1.6
14+
factory-boy==2.10.0
1415
Flask==0.12.2
1516
Flask-Babel==0.11.2
1617
Flask-Compress==1.4.0
@@ -26,6 +27,7 @@ ipython-genutils==0.2.0
2627
itsdangerous==0.24
2728
Jinja2==2.10
2829
MarkupSafe==1.0
30+
mock==2.0.0
2931
newrelic
3032
path.py==10.5
3133
pathlib2==2.3.0
@@ -40,6 +42,8 @@ pycparser==2.18
4042
pyflakes==1.6.0
4143
Pygments==2.2.0
4244
pyOpenSSL==17.5.0
45+
pytest==3.5.0
46+
pytest-env==0.6.2
4347
python-dateutil==2.6.1
4448
python-env==1.0.0
4549
python-http-client==3.0.0
@@ -53,6 +57,7 @@ service-identity==17.0.0
5357
simplegeneric==0.8.1
5458
six==1.11.0
5559
SQLAlchemy==1.2.1
60+
testing.postgresql==1.3.0
5661
traitlets==4.3.2
5762
urllib3==1.22
5863
wcwidth==0.1.7

testing/all_tests.py

-7
This file was deleted.

tests/__init__.py

Whitespace-only changes.

tests/conftest.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import pytest
2+
from testing.postgresql import Postgresql
3+
from mock import patch
4+
5+
from app import app as flask_app
6+
from database import db as _db
7+
from config import constants
8+
9+
# importing to register views
10+
from views import web_views # noqa
11+
12+
13+
class TestConfig(object):
14+
SECRET_KEY = constants.FLASK_SECRET_KEY
15+
16+
SQLALCHEMY_TRACK_MODIFICATIONS = False
17+
SQLALCHEMY_ECHO = False
18+
19+
RECAPTCHA_SITE_KEY = constants.RECAPTCHA_SITE_KEY
20+
RECAPTCHA_SECRET_KEY = constants.RECAPTCHA_SECRET_KEY
21+
RECAPTCHA_SIZE = constants.RECAPTCHA_SIZE
22+
SERVER_NAME = 'localhost'
23+
24+
25+
@pytest.yield_fixture(scope='session')
26+
def app():
27+
_app = flask_app
28+
_app.config.from_object(__name__ + '.TestConfig')
29+
with Postgresql() as postgresql:
30+
_app.config['SQLALCHEMY_DATABASE_URI'] = postgresql.url()
31+
ctx = _app.app_context()
32+
ctx.push()
33+
34+
yield _app
35+
36+
ctx.pop()
37+
38+
39+
@pytest.yield_fixture
40+
def client(app):
41+
"""A Flask test client. An instance of :class:`flask.testing.TestClient`
42+
by default.
43+
"""
44+
with app.test_client() as client:
45+
yield client
46+
47+
48+
@pytest.yield_fixture(scope='session')
49+
def db(app):
50+
_db.app = app
51+
_db.init_app(app)
52+
_db.create_all()
53+
54+
yield _db
55+
56+
_db.drop_all()
57+
58+
59+
@pytest.fixture(scope='function', autouse=True)
60+
def session(db):
61+
connection = db.engine.connect()
62+
transaction = connection.begin()
63+
64+
options = dict(bind=connection, binds={})
65+
session_ = db.create_scoped_session(options=options)
66+
67+
db.session = session_
68+
69+
yield session_
70+
71+
transaction.rollback()
72+
connection.close()
73+
session_.remove()
74+
75+
76+
@pytest.yield_fixture(scope='function')
77+
def mock_captcha(app):
78+
patcher = patch('views.web_views.recaptcha', return_value=True)
79+
yield patcher.start()
80+
patcher.stop()
81+
82+
83+
@pytest.yield_fixture(scope='function')
84+
def mock_send_message(app):
85+
patcher = patch('util.sendgrid_wrapper.send_message', return_value=True)
86+
yield patcher.start()
87+
patcher.stop()

tests/factories.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from factory import alchemy, Faker
2+
3+
from database import db
4+
from database.db_models import Interest, Presale, EmailList
5+
6+
7+
class PresaleFactory(alchemy.SQLAlchemyModelFactory):
8+
class Meta(object):
9+
model = Presale
10+
sqlalchemy_session = db.session # the SQLAlchemy session object
11+
12+
full_name = Faker('name')
13+
email = Faker('safe_email')
14+
accredited = True
15+
entity_type = 'Individual'
16+
desired_allocation = '30000'
17+
desired_allocation_currency = "USD"
18+
citizenship = "US"
19+
sending_addr = "0x0000000000000000000000000000000000000000"
20+
note = Faker('sentence', nb_words=8)
21+
ip_addr = Faker('ipv4')
22+
23+
24+
class InterestFactory(alchemy.SQLAlchemyModelFactory):
25+
class Meta(object):
26+
model = Interest
27+
sqlalchemy_session = db.session # the SQLAlchemy session object
28+
29+
name = Faker('name')
30+
company_name = Faker('company')
31+
email = Faker('safe_email')
32+
website = Faker('domain_name')
33+
note = Faker('sentence', nb_words=8)
34+
35+
36+
class EmailListFactory(alchemy.SQLAlchemyModelFactory):
37+
class Meta(object):
38+
model = EmailList
39+
sqlalchemy_session = db.session # the SQLAlchemy session object
40+
41+
email = Faker('safe_email')
42+
unsubscribed = False

tests/test_functional.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# test_app.py
2+
import random
3+
from faker import Faker
4+
5+
from flask import url_for
6+
7+
from config.constants import LANGUAGES
8+
from database.db_models import EmailList, Presale, Interest
9+
10+
from .factories import PresaleFactory, InterestFactory
11+
12+
13+
fake = Faker()
14+
15+
16+
def test_root_returns_302(client):
17+
res = client.get(url_for('root'))
18+
assert res.status_code == 302
19+
20+
21+
def test_index_returns_200(client):
22+
res = client.get(url_for('index', lang_code=random.choice(LANGUAGES)))
23+
assert res.status_code == 200
24+
25+
26+
def test_join_mailing_and_unsubscribe(mock_send_message, session, client):
27+
data = {
28+
"email": fake.safe_email(),
29+
"ip_addr": fake.ipv4(),
30+
}
31+
res = client.post(url_for('join_mailing_list'),
32+
data=data)
33+
34+
assert res.status_code == 200
35+
assert EmailList.query.filter_by(email=data['email']).first() is not None
36+
37+
# try to unsubscribe the created EmailList object above
38+
res = client.get("{url}?email={param}".
39+
format(url=url_for('unsubscribe'),
40+
param=data['email']))
41+
42+
assert res.status_code == 302
43+
assert EmailList.query.filter_by(email=data['email'],
44+
unsubscribed=True).first() is not None
45+
46+
47+
def test_join_presale(mock_send_message, mock_captcha, session, client):
48+
data = PresaleFactory.stub().__dict__
49+
data['confirm'] = True
50+
51+
res = client.post(url_for('join_presale'), data=data)
52+
created_obj = Presale.query.filter_by(email=data['email']).first()
53+
54+
assert created_obj.id is not None
55+
assert res.status_code == 200
56+
57+
58+
def test_partners_interest(mock_send_message, mock_captcha, session, client):
59+
data = InterestFactory.stub().__dict__
60+
data['confirm'] = True
61+
62+
res = client.post(url_for('partners_interest'), data=data)
63+
created_obj = Interest.query.filter_by(email=data['email']).first()
64+
65+
assert created_obj.id is not None
66+
assert res.status_code == 200

tests/test_models.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from .factories import InterestFactory, PresaleFactory, EmailListFactory
2+
3+
4+
def test_interest_model(session):
5+
created_obj = InterestFactory.build()
6+
session.add(created_obj)
7+
session.commit()
8+
9+
assert created_obj.id is not None
10+
assert created_obj.created_at is not None
11+
12+
13+
def test_presale_model(session):
14+
created_obj = PresaleFactory.build()
15+
session.add(created_obj)
16+
session.commit()
17+
18+
assert created_obj.id is not None
19+
assert created_obj.created_at is not None
20+
21+
22+
def test_email_list_model(session):
23+
created_obj = EmailListFactory.build()
24+
session.add(created_obj)
25+
session.commit()
26+
27+
assert created_obj.created_at is not None

0 commit comments

Comments
 (0)