diff --git a/config.py b/config.py
index 0d9e342a96b7a86c8c9fd74fb604a76a4b3b2679..4a1c3ab007e92436ec4996f62a432fb51e4dfda9 100644
--- a/config.py
+++ b/config.py
@@ -18,7 +18,11 @@ class DevelopmentConfig(Config):
     SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data_dev.sqlite')
 
 
-# class TestingConfig(Config):
+class TestingConfig(Config):
+    TESTING = True
+    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
+        'sqlite://'
+    WTF_CSRF_ENABLED = False
 
 
 # class ProductionConfig(Config):
@@ -26,7 +30,7 @@ class DevelopmentConfig(Config):
 
 config = {
     'development': DevelopmentConfig,
-    # 'testing': TestingConfig,
+    'testing': TestingConfig,
     # 'production': ProductionConfig,
 
     'default': DevelopmentConfig
diff --git a/opaque.py b/opaque.py
index 75a1e5622577772e2eca90b5fb939faebf48641c..0e60328917da677cf01b077f49a50e2bc78b1106 100644
--- a/opaque.py
+++ b/opaque.py
@@ -11,3 +11,11 @@ migrate = Migrate(app, db)
 @app.shell_context_processor
 def make_shell_context():
     return dict(db=db, User=User, Role=Role)
+
+
+@app.cli.command()
+def test():
+    """Run the unit tests."""
+    import unittest
+    tests = unittest.TestLoader().discover('tests')
+    unittest.TextTestRunner(verbosity=2).run(tests)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/test_basics.py b/tests/test_basics.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fdf4983b03e755239aca1ef4a5dc29079b3850f
--- /dev/null
+++ b/tests/test_basics.py
@@ -0,0 +1,22 @@
+import unittest
+from flask import current_app
+from app import create_app, db
+
+
+class BasicsTestCase(unittest.TestCase):
+    def setUp(self):
+        self.app = create_app('testing')
+        self.app_context = self.app.app_context()
+        self.app_context.push()
+        db.create_all()
+
+    def tearDown(self):
+        db.session.remove()
+        db.drop_all()
+        self.app_context.pop()
+
+    def test_app_exists(self):
+        self.assertFalse(current_app is None)
+
+    def test_app_is_testing(self):
+        self.assertTrue(current_app.config['TESTING'])
diff --git a/tests/test_user_model.py b/tests/test_user_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c794b0bb1174d91850b88738ec9b162e4891ba6
--- /dev/null
+++ b/tests/test_user_model.py
@@ -0,0 +1,23 @@
+import unittest
+from app.models import User
+
+
+class UserModelTestCase(unittest.TestCase):
+    def test_password_setter(self):
+        u = User(password='cat')
+        self.assertTrue(u.password_hash is not None)
+
+    def test_no_password_getter(self):
+        u = User(password='cat')
+        with self.assertRaises(AttributeError):
+            u.password
+
+    def test_password_verification(self):
+        u = User(password='cat')
+        self.assertTrue(u.verify_password('cat'))
+        self.assertFalse(u.verify_password('dog'))
+
+    def test_password_salts_are_random(self):
+        u = User(password='cat')
+        u2 = User(password='cat')
+        self.assertTrue(u.password_hash != u2.password_hash)