Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Build a Social Network with Flask Tacocat Challenge The Challenge

The test_database of peewee is deprecated

I got an error: "ImportError: cannot import name 'test_database" when running app_tests.py in my client.

After google it , I found this post on Github: https://github.com/coleifer/peewee/issues/1440 which mentioned that test_database has been deprecated.

Should I downgrade my peewee version to run the tests? If so, what version is it?

2 Answers

David McGarvey
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
David McGarvey
Full Stack JavaScript Techdegree Graduate 27,424 Points

Chris Howell helped me solve this one. In the latest version of peewee, test_database is no longer in use. So you need to use an older version of peewee for this project if you want to use the tests the same way as Kenneth intended. To "downgrade" your version of peewee, use: pip install -U peewee==2.10.2

Rather than downgrade to an outdated version, as per http://docs.peewee-orm.com/en/latest/peewee/api.html#Database.bind_ctx you can use the following (replacing the test_database() function):

MODELS = (User,Taco)

# Bind the given models to the db for the duration of wrapped block.
def use_test_database(fn):
    @wraps(fn)
    def inner(self):
        with TEST_DB.bind_ctx(MODELS):
            TEST_DB.create_tables(MODELS)
            try:
                fn(self)
            finally:
                TEST_DB.drop_tables(MODELS)
    return inner

You can then use this decorator instead of the test_database() wrapper. Here's the entire app_tests.py file updated to work on the latest (as of Feb. 2021) version of Peewee:

import unittest
from functools import wraps

from peewee import *

import tacocat
from models import User, Taco

TEST_DB = SqliteDatabase(':memory:')
TEST_DB.connect()
TEST_DB.create_tables([User, Taco], safe=True)

USER_DATA = {
    'email': 'test_0@example.com',
    'password': 'password'
}

MODELS = (User,Taco)


# Bind the given models to the db for the duration of wrapped block.
def use_test_database(fn):
    @wraps(fn)
    def inner(self):
        with TEST_DB.bind_ctx(MODELS):
            TEST_DB.create_tables(MODELS)
            try:
                fn(self)
            finally:
                TEST_DB.drop_tables(MODELS)
    return inner


class UserModelTestCase(unittest.TestCase):
    @staticmethod
    def create_users(count=2):
        for i in range(count):
            User.create_user(
                email='test_{}@example.com'.format(i),
                password='password'
            )

    @use_test_database
    def test_create_user(self):
        self.create_users()
        self.assertEqual(User.select().count(), 2)
        self.assertNotEqual(
            User.select().get().password,
            'password'
        )

    @use_test_database
    def test_create_duplicate_user(self):
        self.create_users()
        with self.assertRaises(ValueError):
            User.create_user(
                email='test_1@example.com',
                password='password'
            )


class TacoModelTestCase(unittest.TestCase):
    @use_test_database
    def test_taco_creation(self):
        UserModelTestCase.create_users()
        user = User.select().get()
        Taco.create(
            user=user,
            protein='chicken',
            shell='flour',
            cheese=False,
            extras='Gimme some guac.'
        )
        taco = Taco.select().get()

        self.assertEqual(
            Taco.select().count(),
            1
        )
        self.assertEqual(taco.user, user)


class ViewTestCase(unittest.TestCase):
    def setUp(self):
        tacocat.app.config['TESTING'] = True
        tacocat.app.config['WTF_CSRF_ENABLED'] = False
        self.app = tacocat.app.test_client()


class UserViewsTestCase(ViewTestCase):
    @use_test_database
    def test_registration(self):
        data = {
            'email': 'test@example.com',
            'password': 'password',
            'password2': 'password'
        }
        rv = self.app.post(
            '/register',
            data=data)
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(rv.location, 'http://localhost/')

    @use_test_database
    def test_good_login(self):
        UserModelTestCase.create_users(1)
        rv = self.app.post('/login', data=USER_DATA)
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(rv.location, 'http://localhost/')

    @use_test_database
    def test_bad_login(self):
        rv = self.app.post('/login', data=USER_DATA)
        self.assertEqual(rv.status_code, 200)

    @use_test_database
    def test_logout(self):
        # Create and login the user
        UserModelTestCase.create_users(1)
        self.app.post('/login', data=USER_DATA)

        rv = self.app.get('/logout')
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(rv.location, 'http://localhost/')

    @use_test_database
    def test_logged_out_menu(self):
        rv = self.app.get('/')
        self.assertIn("sign up", rv.get_data(as_text=True).lower())
        self.assertIn("log in", rv.get_data(as_text=True).lower())

    @use_test_database
    def test_logged_in_menu(self):
        UserModelTestCase.create_users(1)
        self.app.post('/login', data=USER_DATA)
        rv = self.app.get('/')
        self.assertIn("add a new taco", rv.get_data(as_text=True).lower())
        self.assertIn("log out", rv.get_data(as_text=True).lower())


class TacoViewsTestCase(ViewTestCase):
    @use_test_database
    def test_empty_db(self):
        rv = self.app.get('/')
        self.assertIn("no tacos yet", rv.get_data(as_text=True).lower())

    @use_test_database
    def test_taco_create(self):
        taco_data = {
            'protein': 'chicken',
            'shell': 'flour',
            'cheese': False,
            'extras': 'Gimme some guac.'
        }
        UserModelTestCase.create_users(1)
        self.app.post('/login', data=USER_DATA)

        taco_data['user'] = User.select().get()
        rv = self.app.post('/taco', data=taco_data)
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(rv.location, 'http://localhost/')
        self.assertEqual(Taco.select().count(), 1)

    @use_test_database
    def test_taco_list(self):
        taco_data = {
            'protein': 'chicken',
            'shell': 'flour',
            'cheese': False,
            'extras': 'Gimme some guac.'
        }
        UserModelTestCase.create_users(1)
        taco_data['user'] = User.select().get()
        Taco.create(**taco_data)

        rv = self.app.get('/')
        self.assertNotIn('no tacos yet', rv.get_data(as_text=True))
        self.assertIn(taco_data['extras'], rv.get_data(as_text=True))


if __name__ == '__main__':
    unittest.main()