You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2024/10/30 16:02:26 UTC

(allura) 02/03: py312 prep - Convert remaining unittest assertions -> pytest

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 62a0ce37f789c16ccc2ca195c9993b902255c124
Author: Kenton Taylor <kt...@slashdotmedia.com>
AuthorDate: Tue Oct 22 15:01:01 2024 +0000

    py312 prep - Convert remaining unittest assertions -> pytest
---
 Allura/allura/controllers/site_admin.py            |   4 +-
 Allura/allura/tests/model/test_notification.py     |   3 +-
 Allura/allura/tests/model/test_repo.py             | 255 +++++++++++----------
 Allura/allura/tests/test_decorators.py             |   8 +-
 Allura/allura/tests/test_globals.py                |  68 +++---
 Allura/allura/tests/test_helpers.py                |  22 +-
 Allura/allura/tests/test_markdown.py               |  67 +++---
 Allura/allura/tests/test_utils.py                  |  53 ++---
 Allura/allura/tests/test_validators.py             |  84 ++++---
 Allura/allura/tests/unit/test_app.py               |  91 ++++----
 Allura/allura/tests/unit/test_artifact.py          |   2 +-
 Allura/allura/tests/unit/test_project.py           |  17 +-
 Allura/allura/tests/unit/test_repo.py              |  23 +-
 Allura/allura/tests/unit/test_session.py           |  50 ++--
 ForgeGit/forgegit/tests/model/test_repository.py   |  64 +++---
 .../forgeimporters/github/tests/test_code.py       |  28 +--
 .../forgeimporters/github/tests/test_oauth.py      |   8 +-
 .../forgeimporters/github/tests/test_tracker.py    |  22 +-
 .../forgeimporters/github/tests/test_wiki.py       |  36 ++-
 .../forgeimporters/tests/forge/test_discussion.py  |  56 ++---
 .../forgeimporters/tests/forge/test_tracker.py     | 101 ++++----
 .../tests/github/functional/test_github.py         |   6 +-
 .../forgeimporters/tests/github/test_extractor.py  |  88 ++++---
 .../forgeimporters/tests/github/test_tracker.py    |  68 +++---
 ForgeImporters/forgeimporters/tests/test_base.py   |  58 ++---
 .../forgeimporters/trac/tests/test_tickets.py      |  48 ++--
 ForgeSVN/forgesvn/tests/model/test_repository.py   |  55 +++--
 .../tests/unit/test_root_controller.py             |  24 +-
 ForgeUserStats/forgeuserstats/tests/test_model.py  |  14 +-
 29 files changed, 685 insertions(+), 738 deletions(-)

diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 22b1c3fab..19ed71e4a 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -18,7 +18,7 @@
 import re
 import logging
 from datetime import datetime, timedelta
-import pipes
+import shlex
 
 from tg import expose, validate, flash, config, redirect
 from tg.decorators import with_trailing_slash, without_trailing_slash
@@ -413,7 +413,7 @@ class DeleteProjectsController:
             redirect('.')
         task_params = ' '.join(task_params)
         if reason:
-            task_params = f'-r {pipes.quote(reason)} {task_params}'
+            task_params = f'-r {shlex.quote(reason)} {task_params}'
         if disable_users:
             task_params = f'--disable-users {task_params}'
         DeleteProjects.post(task_params)
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index 9fdf2385c..557151de3 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -283,8 +283,7 @@ class TestPostNotifications(unittest.TestCase):
         assert 'test@mail.com is subscribed to http://test1.com' in footer
         assert 'admin can change settings at http://test2.com' in footer
         footer = MailFooter.standard(M.Notification())
-        self.assertIn('Sent from localhost because you indicated interest',
-                      footer)
+        assert 'Sent from localhost because you indicated interest' in footer
 
     def _subscribe(self, **kw):
         self.pg.subscribe(type='direct', **kw)
diff --git a/Allura/allura/tests/model/test_repo.py b/Allura/allura/tests/model/test_repo.py
index 0a91d690b..c9b872ae1 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -98,7 +98,7 @@ class RepoTestBase(unittest.TestCase):
             if base_url:
                 values['base_url'] = base_url
             with mock.patch.dict(config, values, clear=True):
-                self.assertEqual(result, repo.refresh_url())
+                assert result == repo.refresh_url()
 
     def test_clone_command_categories(self):
         c.app = mock.Mock(**{'config._id': 'deadbeef'})
@@ -221,47 +221,47 @@ class TestLastCommit(unittest.TestCase):
             'dir1/file2',
         ])
         lcd = M.repository.LastCommit.get(commit1.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit1.message)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 2)
-        self.assertEqual(lcd.by_name['file1'], commit1._id)
-        self.assertEqual(lcd.by_name['dir1'], commit1._id)
+        assert self.repo._commits[lcd.commit_id].message == commit1.message
+        assert lcd.path == ''
+        assert len(lcd.entries) == 2
+        assert lcd.by_name['file1'] == commit1._id
+        assert lcd.by_name['dir1'] == commit1._id
 
     def test_multiple_commits_no_overlap(self):
         commit1 = self._add_commit('Commit 1', ['file1'])
         commit2 = self._add_commit('Commit 2', ['file1', 'dir1/file1'], ['dir1/file1'], [commit1])
         commit3 = self._add_commit('Commit 3', ['file1', 'dir1/file1', 'file2'], ['file2'], [commit2])
         lcd = M.repository.LastCommit.get(commit3.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.commit_id, commit3._id)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 3)
-        self.assertEqual(lcd.by_name['file1'], commit1._id)
-        self.assertEqual(lcd.by_name['dir1'], commit2._id)
-        self.assertEqual(lcd.by_name['file2'], commit3._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.commit_id == commit3._id
+        assert lcd.path == ''
+        assert len(lcd.entries) == 3
+        assert lcd.by_name['file1'] == commit1._id
+        assert lcd.by_name['dir1'] == commit2._id
+        assert lcd.by_name['file2'] == commit3._id
 
     def test_multiple_commits_with_overlap(self):
         commit1 = self._add_commit('Commit 1', ['file1'])
         commit2 = self._add_commit('Commit 2', ['file1', 'dir1/file1'], ['dir1/file1'], [commit1])
         commit3 = self._add_commit('Commit 3', ['file1', 'dir1/file1', 'file2'], ['file1', 'file2'], [commit2])
         lcd = M.repository.LastCommit.get(commit3.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 3)
-        self.assertEqual(lcd.by_name['file1'], commit3._id)
-        self.assertEqual(lcd.by_name['dir1'], commit2._id)
-        self.assertEqual(lcd.by_name['file2'], commit3._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.path == ''
+        assert len(lcd.entries) == 3
+        assert lcd.by_name['file1'] == commit3._id
+        assert lcd.by_name['dir1'] == commit2._id
+        assert lcd.by_name['file2'] == commit3._id
 
     def test_multiple_commits_subdir_change(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1/file1'])
         commit2 = self._add_commit('Commit 2', ['file1', 'dir1/file1', 'dir1/file2'], ['dir1/file2'], [commit1])
         commit3 = self._add_commit('Commit 3', ['file1', 'dir1/file1', 'dir1/file2'], ['dir1/file1'], [commit2])
         lcd = M.repository.LastCommit.get(commit3.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 2)
-        self.assertEqual(lcd.by_name['file1'], commit1._id)
-        self.assertEqual(lcd.by_name['dir1'], commit3._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.path == ''
+        assert len(lcd.entries) == 2
+        assert lcd.by_name['file1'] == commit1._id
+        assert lcd.by_name['dir1'] == commit3._id
 
     def test_subdir_lcd(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1/file1'])
@@ -269,11 +269,11 @@ class TestLastCommit(unittest.TestCase):
         commit3 = self._add_commit('Commit 3', ['file1', 'dir1/file1', 'dir1/file2'], ['dir1/file1'], [commit2])
         tree = self._build_tree(commit3, '/dir1', ['file1', 'file2'])
         lcd = M.repository.LastCommit.get(tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.path, 'dir1')
-        self.assertEqual(len(lcd.entries), 2)
-        self.assertEqual(lcd.by_name['file1'], commit3._id)
-        self.assertEqual(lcd.by_name['file2'], commit2._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.path == 'dir1'
+        assert len(lcd.entries) == 2
+        assert lcd.by_name['file1'] == commit3._id
+        assert lcd.by_name['file2'] == commit2._id
 
     def test_subdir_lcd_prev_commit(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1/file1'])
@@ -282,29 +282,29 @@ class TestLastCommit(unittest.TestCase):
         commit4 = self._add_commit('Commit 4', ['file1', 'dir1/file1', 'dir1/file2', 'file2'], ['file2'], [commit3])
         tree = self._build_tree(commit4, '/dir1', ['file1', 'file2'])
         lcd = M.repository.LastCommit.get(tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.path, 'dir1')
-        self.assertEqual(len(lcd.entries), 2)
-        self.assertEqual(lcd.by_name['file1'], commit3._id)
-        self.assertEqual(lcd.by_name['file2'], commit2._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.path == 'dir1'
+        assert len(lcd.entries) == 2
+        assert lcd.by_name['file1'] == commit3._id
+        assert lcd.by_name['file2'] == commit2._id
 
     def test_subdir_lcd_always_empty(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1'])
         commit2 = self._add_commit('Commit 2', ['file1', 'file2'], ['file2'], [commit1])
         tree = self._build_tree(commit2, '/dir1', [])
         lcd = M.repository.LastCommit.get(tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit1.message)
-        self.assertEqual(lcd.path, 'dir1')
-        self.assertEqual(lcd.entries, [])
+        assert self.repo._commits[lcd.commit_id].message == commit1.message
+        assert lcd.path == 'dir1'
+        assert lcd.entries == []
 
     def test_subdir_lcd_emptied(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1/file1'])
         commit2 = self._add_commit('Commit 2', ['file1'], ['dir1/file1'], [commit1])
         tree = self._build_tree(commit2, '/dir1', [])
         lcd = M.repository.LastCommit.get(tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit2.message)
-        self.assertEqual(lcd.path, 'dir1')
-        self.assertEqual(lcd.entries, [])
+        assert self.repo._commits[lcd.commit_id].message == commit2.message
+        assert lcd.path == 'dir1'
+        assert lcd.entries == []
 
     def test_existing_lcd_unchained(self):
         commit1 = self._add_commit('Commit 1', ['file1', 'dir1/file1'])
@@ -325,10 +325,10 @@ class TestLastCommit(unittest.TestCase):
         session(prev_lcd).flush()
         tree = self._build_tree(commit3, '/dir1', ['file1', 'file2'])
         lcd = M.repository.LastCommit.get(tree)
-        self.assertEqual(lcd._id, prev_lcd._id)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit2.message)
-        self.assertEqual(lcd.path, 'dir1')
-        self.assertEqual(lcd.entries, prev_lcd.entries)
+        assert lcd._id == prev_lcd._id
+        assert self.repo._commits[lcd.commit_id].message == commit2.message
+        assert lcd.path == 'dir1'
+        assert lcd.entries == prev_lcd.entries
 
     def test_existing_lcd_partial(self):
         commit1 = self._add_commit('Commit 1', ['file1'])
@@ -352,13 +352,13 @@ class TestLastCommit(unittest.TestCase):
         )
         session(prev_lcd).flush()
         lcd = M.repository.LastCommit.get(commit4.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit4.message)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 4)
-        self.assertEqual(lcd.by_name['file1'], commit1._id)
-        self.assertEqual(lcd.by_name['file2'], commit4._id)
-        self.assertEqual(lcd.by_name['file3'], commit3._id)
-        self.assertEqual(lcd.by_name['file4'], commit4._id)
+        assert self.repo._commits[lcd.commit_id].message == commit4.message
+        assert lcd.path == ''
+        assert len(lcd.entries) == 4
+        assert lcd.by_name['file1'] == commit1._id
+        assert lcd.by_name['file2'] == commit4._id
+        assert lcd.by_name['file3'] == commit3._id
+        assert lcd.by_name['file4'] == commit4._id
 
     def test_missing_add_record(self):
         self._add_commit('Commit 1', ['file1'])
@@ -379,11 +379,11 @@ class TestLastCommit(unittest.TestCase):
         commit3 = self._add_commit('Commit 3', ['file1', 'dir1/file1', 'file2'], ['file2'], [commit2])
         with h.push_config(config, lcd_timeout=-1000):
             lcd = M.repository.LastCommit.get(commit3.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.commit_id, commit3._id)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 1)
-        self.assertEqual(lcd.by_name['file2'], commit3._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.commit_id == commit3._id
+        assert lcd.path == ''
+        assert len(lcd.entries) == 1
+        assert lcd.by_name['file2'] == commit3._id
 
     def test_loop(self):
         commit1 = self._add_commit('Commit 1', ['file1'])
@@ -392,12 +392,12 @@ class TestLastCommit(unittest.TestCase):
         commit2.parent_ids = [commit3._id]
         session(commit2).flush(commit2)
         lcd = M.repository.LastCommit.get(commit3.tree)
-        self.assertEqual(self.repo._commits[lcd.commit_id].message, commit3.message)
-        self.assertEqual(lcd.commit_id, commit3._id)
-        self.assertEqual(lcd.path, '')
-        self.assertEqual(len(lcd.entries), 3)
-        self.assertEqual(lcd.by_name['dir1'], commit2._id)
-        self.assertEqual(lcd.by_name['file2'], commit3._id)
+        assert self.repo._commits[lcd.commit_id].message == commit3.message
+        assert lcd.commit_id == commit3._id
+        assert lcd.path == ''
+        assert len(lcd.entries) == 3
+        assert lcd.by_name['dir1'] == commit2._id
+        assert lcd.by_name['file2'] == commit3._id
 
 
 class TestModelCache(unittest.TestCase):
@@ -405,15 +405,15 @@ class TestModelCache(unittest.TestCase):
         self.cache = M.repository.ModelCache()
 
     def test_normalize_query(self):
-        self.assertEqual(self.cache._normalize_query(
-            {'foo': 1, 'bar': 2}), (('bar', 2), ('foo', 1)))
+        assert self.cache._normalize_query(
+            {'foo': 1, 'bar': 2}) == (('bar', 2), ('foo', 1))
 
     def test_model_query(self):
         q = mock.Mock(spec_set=['query'], query='foo')
         m = mock.Mock(spec_set=['m'], m='bar')
         n = mock.Mock(spec_set=['foo'], foo='qux')
-        self.assertEqual(self.cache._model_query(q), 'foo')
-        self.assertEqual(self.cache._model_query(m), 'bar')
+        assert self.cache._model_query(q) == 'foo'
+        assert self.cache._model_query(m) == 'bar'
         with pytest.raises(AttributeError):
             self.cache._model_query([n])
 
@@ -427,11 +427,11 @@ class TestModelCache(unittest.TestCase):
 
         val = self.cache.get(M.repository.Tree, {'_id': 'foo'})
         tr_get.assert_called_with(_id='foo')
-        self.assertEqual(val, tree)
+        assert val == tree
 
         val = self.cache.get(M.repository.LastCommit, {'_id': 'foo'})
         lc_get.assert_called_with(_id='foo')
-        self.assertEqual(val, lcd)
+        assert val == lcd
 
     @mock.patch.object(M.repository.Tree.query, 'get')
     def test_get_no_query(self, tr_get):
@@ -439,20 +439,21 @@ class TestModelCache(unittest.TestCase):
             spec=['_id', 'val'], _id='foo', val='bar')
         val = self.cache.get(M.repository.Tree, {'_id': 'foo'})
         tr_get.assert_called_once_with(_id='foo')
-        self.assertEqual(val, tree1)
+        assert val == tree1
 
         tree2 = tr_get.return_value = mock.Mock(_id='foo', val='qux')
         val = self.cache.get(M.repository.Tree, {'_id': 'foo'})
         tr_get.assert_called_once_with(_id='foo')
-        self.assertEqual(val, tree1)
+        assert val == tree1
+
 
     def test_set(self):
         tree = mock.Mock(spec=['_id', 'test_set'], _id='foo', val='test_set')
         self.cache.set(M.repository.Tree, {'val': 'test_set'}, tree)
-        self.assertEqual(self.cache._query_cache,
-                         {M.repository.Tree: {(('val', 'test_set'),): 'foo'}})
-        self.assertEqual(self.cache._instance_cache,
-                         {M.repository.Tree: {'foo': tree}})
+        assert self.cache._query_cache == \
+                         {M.repository.Tree: {(('val', 'test_set'),): 'foo'}}
+        assert self.cache._instance_cache == \
+                         {M.repository.Tree: {'foo': tree}}
 
     @mock.patch('bson.ObjectId')
     def test_set_none_id(self, obj_id):
@@ -460,51 +461,51 @@ class TestModelCache(unittest.TestCase):
         tree = mock.Mock(spec=['_id', 'test_set'], _id=None, val='test_set')
         self.cache.set(M.repository.Tree, {'val1': 'test_set1'}, tree)
         self.cache.set(M.repository.Tree, {'val2': 'test_set2'}, tree)
-        self.assertEqual(dict(self.cache._query_cache[M.repository.Tree]), {
+        assert dict(self.cache._query_cache[M.repository.Tree]) == {
             (('val1', 'test_set1'),): 'OBJID',
             (('val2', 'test_set2'),): 'OBJID',
-        })
-        self.assertEqual(self.cache._instance_cache,
-                         {M.repository.Tree: {'OBJID': tree}})
+        }
+        assert self.cache._instance_cache == \
+                         {M.repository.Tree: {'OBJID': tree}}
         tree._id = '_id'
-        self.assertEqual(self.cache.get(M.repository.Tree, {'val1': 'test_set1'}), tree)
-        self.assertEqual(self.cache.get(M.repository.Tree, {'val2': 'test_set2'}), tree)
+        assert self.cache.get(M.repository.Tree, {'val1': 'test_set1'}) == tree
+        assert self.cache.get(M.repository.Tree, {'val2': 'test_set2'}) == tree
         self.cache.set(M.repository.Tree, {'val1': 'test_set2'}, tree)
-        self.assertEqual(self.cache.get(M.repository.Tree, {'val1': 'test_set1'}), tree)
-        self.assertEqual(self.cache.get(M.repository.Tree, {'val2': 'test_set2'}), tree)
+        assert self.cache.get(M.repository.Tree, {'val1': 'test_set1'}) == tree
+        assert self.cache.get(M.repository.Tree, {'val2': 'test_set2'}) == tree
 
     @mock.patch('bson.ObjectId')
     def test_set_none_val(self, obj_id):
         obj_id.return_value = 'OBJID'
         self.cache.set(M.repository.Tree, {'val1': 'test_set1'}, None)
         self.cache.set(M.repository.Tree, {'val2': 'test_set2'}, None)
-        self.assertEqual(dict(self.cache._query_cache[M.repository.Tree]), {
+        assert dict(self.cache._query_cache[M.repository.Tree]) == {
             (('val1', 'test_set1'),): None,
             (('val2', 'test_set2'),): None,
-        })
-        self.assertEqual(dict(self.cache._instance_cache[M.repository.Tree]), {})
+        }
+        assert dict(self.cache._instance_cache[M.repository.Tree]) == {}
         tree1 = mock.Mock(spec=['_id', 'val'], _id='tree1', val='test_set')
         tree2 = mock.Mock(spec=['_model_cache_id', '_id', 'val'],
                           _model_cache_id='tree2', _id='tree1', val='test_set2')
         self.cache.set(M.repository.Tree, {'val1': 'test_set1'}, tree1)
         self.cache.set(M.repository.Tree, {'val2': 'test_set2'}, tree2)
-        self.assertEqual(dict(self.cache._query_cache[M.repository.Tree]), {
+        assert dict(self.cache._query_cache[M.repository.Tree]) == {
             (('val1', 'test_set1'),): 'tree1',
             (('val2', 'test_set2'),): 'tree2',
-        })
-        self.assertEqual(dict(self.cache._instance_cache[M.repository.Tree]), {
+        }
+        assert dict(self.cache._instance_cache[M.repository.Tree]) == {
             'tree1': tree1,
             'tree2': tree2,
-        })
+        }
 
     def test_instance_ids(self):
         tree1 = mock.Mock(spec=['_id', 'val'], _id='id1', val='tree1')
         tree2 = mock.Mock(spec=['_id', 'val'], _id='id2', val='tree2')
         self.cache.set(M.repository.Tree, {'val': 'tree1'}, tree1)
         self.cache.set(M.repository.Tree, {'val': 'tree2'}, tree2)
-        self.assertEqual(set(self.cache.instance_ids(M.repository.Tree)),
-                         {'id1', 'id2'})
-        self.assertEqual(self.cache.instance_ids(M.repository.LastCommit), [])
+        assert set(self.cache.instance_ids(M.repository.Tree)) == \
+                         {'id1', 'id2'}
+        assert self.cache.instance_ids(M.repository.LastCommit) == []
 
     @mock.patch.object(M.repository.Tree.query, 'find')
     def test_batch_load(self, tr_find):
@@ -515,14 +516,14 @@ class TestModelCache(unittest.TestCase):
 
         self.cache.batch_load(M.repository.Tree, {'foo': {'$in': 'bar'}})
         tr_find.assert_called_with({'foo': {'$in': 'bar'}})
-        self.assertEqual(self.cache._query_cache[M.repository.Tree], {
+        assert self.cache._query_cache[M.repository.Tree] == {
             (('foo', 1),): 'id1',
             (('foo', 2),): 'id2',
-        })
-        self.assertEqual(self.cache._instance_cache[M.repository.Tree], {
+        }
+        assert self.cache._instance_cache[M.repository.Tree] == {
             'id1': m1,
             'id2': m2,
-        })
+        }
 
     @mock.patch.object(M.repository.Tree.query, 'find')
     def test_batch_load_attrs(self, tr_find):
@@ -533,14 +534,14 @@ class TestModelCache(unittest.TestCase):
 
         self.cache.batch_load(M.repository.Tree, {'foo': {'$in': 'bar'}}, ['qux'])
         tr_find.assert_called_with({'foo': {'$in': 'bar'}})
-        self.assertEqual(self.cache._query_cache[M.repository.Tree], {
+        assert self.cache._query_cache[M.repository.Tree] == {
             (('qux', 3),): 'id1',
             (('qux', 5),): 'id2',
-        })
-        self.assertEqual(self.cache._instance_cache[M.repository.Tree], {
+        }
+        assert self.cache._instance_cache[M.repository.Tree] == {
             'id1': m1,
             'id2': m2,
-        })
+        }
 
     def test_pruning(self):
         cache = M.repository.ModelCache(max_queries=3, max_instances=2)
@@ -555,19 +556,19 @@ class TestModelCache(unittest.TestCase):
         cache.set(M.repository.Tree, {'_id': 'foo'}, tree4)
         cache.get(M.repository.Tree, {'_id': 'f00'})
         cache.set(M.repository.Tree, {'val': 'b4r'}, tree3)
-        self.assertEqual(cache._query_cache, {
+        assert cache._query_cache == {
             M.repository.Tree: {
                 (('_id', 'foo'),): 'foo',
                 (('_id', 'f00'),): 'f00',
                 (('val', 'b4r'),): 'f00',
             },
-        })
-        self.assertEqual(cache._instance_cache, {
+        }
+        assert cache._instance_cache == {
             M.repository.Tree: {
                 'f00': tree3,
                 'foo': tree4,
             },
-        })
+        }
 
     def test_pruning_query_vs_instance(self):
         cache = M.repository.ModelCache(max_queries=3, max_instances=2)
@@ -582,15 +583,15 @@ class TestModelCache(unittest.TestCase):
         cache.set(M.repository.Tree, {'keep_query_2': 'bar'}, tree1)
         # should drop tree2, not tree1, from _instance_cache
         cache.set(M.repository.Tree, {'drop_query_2': 'bar'}, tree3)
-        self.assertEqual(cache._query_cache[M.repository.Tree], {
+        assert cache._query_cache[M.repository.Tree] == {
             (('drop_query_1', 'bar'),): 'tree2',
             (('keep_query_2', 'bar'),): 'keep',
             (('drop_query_2', 'bar'),): 'tree3',
-        })
-        self.assertEqual(cache._instance_cache[M.repository.Tree], {
+        }
+        assert cache._instance_cache[M.repository.Tree] == {
             'keep': tree1,
             'tree3': tree3,
-        })
+        }
 
     @mock.patch('bson.ObjectId')
     def test_pruning_no_id(self, obj_id):
@@ -601,14 +602,14 @@ class TestModelCache(unittest.TestCase):
         cache.set(M.repository.Tree, {'query_1': 'bar'}, tree1)
         cache.set(M.repository.Tree, {'query_2': 'bar'}, tree1)
         cache.set(M.repository.Tree, {'query_3': 'bar'}, tree1)
-        self.assertEqual(cache._instance_cache[M.repository.Tree], {
+        assert cache._instance_cache[M.repository.Tree] == {
             'id1': tree1,
-        })
-        self.assertEqual(cache._query_cache[M.repository.Tree], {
+        }
+        assert cache._query_cache[M.repository.Tree] == {
             (('query_1', 'bar'),): 'id1',
             (('query_2', 'bar'),): 'id1',
             (('query_3', 'bar'),): 'id1',
-        })
+        }
 
     @mock.patch('bson.ObjectId')
     def test_pruning_none(self, obj_id):
@@ -618,12 +619,12 @@ class TestModelCache(unittest.TestCase):
         cache.set(M.repository.Tree, {'query_1': 'bar'}, None)
         cache.set(M.repository.Tree, {'query_2': 'bar'}, None)
         cache.set(M.repository.Tree, {'query_3': 'bar'}, None)
-        self.assertEqual(cache._instance_cache[M.repository.Tree], {})
-        self.assertEqual(cache._query_cache[M.repository.Tree], {
+        assert cache._instance_cache[M.repository.Tree] == {}
+        assert cache._query_cache[M.repository.Tree] == {
             (('query_1', 'bar'),): None,
             (('query_2', 'bar'),): None,
             (('query_3', 'bar'),): None,
-        })
+        }
 
     @mock.patch('allura.model.repository.session')
     @mock.patch.object(M.repository.Tree.query, 'get')
@@ -640,19 +641,19 @@ class TestModelCache(unittest.TestCase):
         cache.get(M.repository.Tree, {'query_1': 'tree2'})
         cache.get(M.repository.Tree, {'query_2': 'tree2'})
         cache.get(M.repository.Tree, {'query_3': 'tree2'})
-        self.assertEqual(cache._query_cache[M.repository.Tree], {
+        assert cache._query_cache[M.repository.Tree] == {
             (('query_1', 'tree2'),): 'tree2',
             (('query_2', 'tree2'),): 'tree2',
             (('query_3', 'tree2'),): 'tree2',
-        })
-        self.assertEqual(cache._instance_cache[M.repository.Tree], {
+        }
+        assert cache._instance_cache[M.repository.Tree] == {
             'tree1': tree1,
             'tree2': tree2,
-        })
-        self.assertEqual(session.call_args_list,
-                         [mock.call(tree1), mock.call(tree2)])
-        self.assertEqual(session.return_value.flush.call_args_list,
-                         [mock.call(tree1), mock.call(tree2)])
+        }
+        assert session.call_args_list == \
+                         [mock.call(tree1), mock.call(tree2)]
+        assert session.return_value.flush.call_args_list == \
+                         [mock.call(tree1), mock.call(tree2)]
         assert not session.return_value.expunge.called
 
     @mock.patch('allura.model.repository.session')
@@ -665,15 +666,15 @@ class TestModelCache(unittest.TestCase):
         cache.set(M.repository.Tree, {'_id': 'tree1'}, tree1)
         cache.set(M.repository.Tree, {'_id': 'tree2'}, tree2)
         cache.set(M.repository.Tree, {'_id': 'tree3'}, tree3)
-        self.assertEqual(cache._query_cache[M.repository.Tree], {
+        assert cache._query_cache[M.repository.Tree] == {
             (('_id', 'tree1'),): 'tree1',
             (('_id', 'tree2'),): 'tree2',
             (('_id', 'tree3'),): 'tree3',
-        })
-        self.assertEqual(cache._instance_cache[M.repository.Tree], {
+        }
+        assert cache._instance_cache[M.repository.Tree] == {
             'tree2': tree2,
             'tree3': tree3,
-        })
+        }
         session.assert_called_once_with(tree1)
         session.return_value.flush.assert_called_once_with(tree1)
         session.return_value.expunge.assert_called_once_with(tree1)
diff --git a/Allura/allura/tests/test_decorators.py b/Allura/allura/tests/test_decorators.py
index 9846520b0..fb700ba63 100644
--- a/Allura/allura/tests/test_decorators.py
+++ b/Allura/allura/tests/test_decorators.py
@@ -51,10 +51,10 @@ class TestTask(TestCase):
         def mock_post(f, args, kw, delay=None):
             assert c.project.notifications_disabled
             assert 'delay' not in kw
-            self.assertEqual(delay, 1)
-            self.assertEqual(kw, dict(foo=2))
-            self.assertEqual(args, ('test',))
-            self.assertEqual(f, func)
+            assert delay == 1
+            assert kw == dict(foo=2)
+            assert args == ('test',)
+            assert f == func
 
         c.project.notifications_disabled = False
         MonQTask.post.side_effect = mock_post
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 26786403d..d139b1887 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -779,24 +779,23 @@ class TestCachedMarkdown(unittest.TestCase):
         with h.push_context('test', 'wiki', neighborhood='Projects'):
             delattr(self.post, 'text_cache')
             html = self.md.cached_convert(self.post, 'text')
-            self.assertEqual(html, self.expected_html)
+            assert html == self.expected_html
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
     def test_non_ascii(self):
         self.post.text = 'å∫ç'
         expected = '<div class="markdown_content"><p>å∫ç</p></div>'
         # test with empty cache
-        self.assertEqual(expected, self.md.cached_convert(self.post, 'text'))
+        assert expected == self.md.cached_convert(self.post, 'text')
         # test with primed cache
-        self.assertEqual(expected, self.md.cached_convert(self.post, 'text'))
+        assert expected == self.md.cached_convert(self.post, 'text')
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
     def test_empty_cache(self):
         html = self.md.cached_convert(self.post, 'text')
-        self.assertEqual(html, self.expected_html)
-        self.assertEqual(html, self.post.text_cache.html)
-        self.assertEqual(hashlib.md5(self.post.text.encode('utf-8')).hexdigest(),
-                         self.post.text_cache.md5)
+        assert html == self.expected_html
+        assert html == self.post.text_cache.html
+        assert hashlib.md5(self.post.text.encode('utf-8')).hexdigest()  == self.post.text_cache.md5
         assert self.post.text_cache.render_time > 0
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
@@ -804,10 +803,9 @@ class TestCachedMarkdown(unittest.TestCase):
         old = self.md.cached_convert(self.post, 'text')
         self.post.text = 'new, different source text'
         html = self.md.cached_convert(self.post, 'text')
-        self.assertNotEqual(old, html)
-        self.assertEqual(html, self.post.text_cache.html)
-        self.assertEqual(hashlib.md5(self.post.text.encode('utf-8')).hexdigest(),
-                         self.post.text_cache.md5)
+        assert old != html
+        assert html == self.post.text_cache.html
+        assert hashlib.md5(self.post.text.encode('utf-8')).hexdigest() == self.post.text_cache.md5
         assert self.post.text_cache.render_time > 0
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='-0.01')
@@ -816,7 +814,7 @@ class TestCachedMarkdown(unittest.TestCase):
         self.md.cached_convert(self.post, 'text')
         with patch.object(self.md, 'convert') as convert_func:
             html = self.md.cached_convert(self.post, 'text')
-            self.assertEqual(html, self.expected_html)
+            assert html == self.expected_html
             self.assertIsInstance(html, Markup)
             assert not convert_func.called
             self.post.text = "text [[include]] pass"
@@ -852,7 +850,7 @@ class TestCachedMarkdown(unittest.TestCase):
     @patch.dict('allura.lib.app_globals.config', {})
     def test_no_threshold_defined(self):
         html = self.md.cached_convert(self.post, 'text')
-        self.assertEqual(html, self.expected_html)
+        assert html == self.expected_html
         self.assertIsNone(self.post.text_cache.md5)
         self.assertIsNone(self.post.text_cache.html)
         self.assertIsNone(self.post.text_cache.render_time)
@@ -860,7 +858,7 @@ class TestCachedMarkdown(unittest.TestCase):
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='foo')
     def test_invalid_threshold(self):
         html = self.md.cached_convert(self.post, 'text')
-        self.assertEqual(html, self.expected_html)
+        assert html == self.expected_html
         self.assertIsNone(self.post.text_cache.md5)
         self.assertIsNone(self.post.text_cache.html)
         self.assertIsNone(self.post.text_cache.render_time)
@@ -868,7 +866,7 @@ class TestCachedMarkdown(unittest.TestCase):
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='99999')
     def test_render_time_below_threshold(self):
         html = self.md.cached_convert(self.post, 'text')
-        self.assertEqual(html, self.expected_html)
+        assert html == self.expected_html
         self.assertIsNone(self.post.text_cache.md5)
         self.assertIsNone(self.post.text_cache.html)
         self.assertIsNone(self.post.text_cache.render_time)
@@ -878,7 +876,7 @@ class TestCachedMarkdown(unittest.TestCase):
         self.md.cached_convert(self.post, 'text')
         required_keys = ['fix7528', 'html', 'md5', 'render_time']
         keys = sorted(self.post.text_cache.keys())
-        self.assertEqual(required_keys, keys)
+        assert required_keys == keys
 
 
 class TestEmojis(unittest.TestCase):
@@ -972,49 +970,49 @@ class TestHandlePaging(unittest.TestCase):
         c.user.set_pref = set_pref
 
     def test_with_limit(self):
-        self.assertEqual(g.handle_paging(10, 0), (10, 0, 0))
-        self.assertEqual(g.handle_paging(10, 2), (10, 2, 20))
+        assert g.handle_paging(10, 0) == (10, 0, 0)
+        assert g.handle_paging(10, 2) == (10, 2, 20)
         # handle paging must not mess up user preferences
-        self.assertEqual(c.user.get_pref('results_per_page'), None)
+        assert c.user.get_pref('results_per_page') is None
         # maximum enforced
-        self.assertEqual(g.handle_paging(99999999, 0), (500, 0, 0))
+        assert g.handle_paging(99999999, 0) == (500, 0, 0)
 
     def test_without_limit(self):
         # default limit = 25
-        self.assertEqual(g.handle_paging(None, 0), (25, 0, 0))
-        self.assertEqual(g.handle_paging(None, 2), (25, 2, 50))
+        assert g.handle_paging(None, 0) == (25, 0, 0)
+        assert g.handle_paging(None, 2) == (25, 2, 50)
         # handle paging must not mess up user preferences
-        self.assertEqual(c.user.get_pref('results_per_page'), None)
+        assert c.user.get_pref('results_per_page') is None
 
         # user has page size preference
         c.user.set_pref('results_per_page', 100)
-        self.assertEqual(g.handle_paging(None, 0), (100, 0, 0))
-        self.assertEqual(g.handle_paging(None, 2), (100, 2, 200))
+        assert g.handle_paging(None, 0) == (100, 0, 0)
+        assert g.handle_paging(None, 2) == (100, 2, 200)
         # handle paging must not mess up user preferences
-        self.assertEqual(c.user.get_pref('results_per_page'), 100)
+        assert c.user.get_pref('results_per_page') == 100
 
     def test_without_limit_with_default(self):
         # default limit is not used when explicitly provided
-        self.assertEqual(g.handle_paging(None, 0, 30), (30, 0, 0))
-        self.assertEqual(g.handle_paging(None, 2, 30), (30, 2, 60))
+        assert g.handle_paging(None, 0, 30) == (30, 0, 0)
+        assert g.handle_paging(None, 2, 30) == (30, 2, 60)
         # handle paging must not mess up user preferences
-        self.assertEqual(c.user.get_pref('results_per_page'), None)
+        assert c.user.get_pref('results_per_page') is None
 
         # user has page size preference, which is not affected by default
         c.user.set_pref('results_per_page', 25)
-        self.assertEqual(g.handle_paging(None, 0, 30), (25, 0, 0))
-        self.assertEqual(g.handle_paging(None, 2, 30), (25, 2, 50))
+        assert g.handle_paging(None, 0, 30) == (25, 0, 0)
+        assert g.handle_paging(None, 2, 30) == (25, 2, 50)
         # handle paging must not mess up user preferences
-        self.assertEqual(c.user.get_pref('results_per_page'), 25)
+        assert c.user.get_pref('results_per_page') == 25
 
     def test_with_invalid_limit(self):
-        self.assertEqual(g.handle_paging('foo', 0, 30), (30, 0, 0))
+        assert g.handle_paging('foo', 0, 30) == (30, 0, 0)
 
         c.user.set_pref('results_per_page', 'bar')
-        self.assertEqual(g.handle_paging(None, 0, 30), (30, 0, 0))
+        assert g.handle_paging(None, 0, 30) == (30, 0, 0)
 
     def test_with_invalid_page(self):
-        self.assertEqual(g.handle_paging(10, 'asdf', 30), (10, 0, 0))
+        assert g.handle_paging(10, 'asdf', 30) == (10, 0, 0)
 
 
 class TestIconRender:
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index e62f4ef6a..07049ef6b 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -59,27 +59,27 @@ class TestMakeSafePathPortion(TestCase):
 
     def test_no_ascii_chars(self):
         s = self.f('Задачи', relaxed=False)
-        self.assertEqual(s, '')
+        assert s == ''
 
     def test_some_ascii_chars(self):
         s = self.f('aßbƒ', relaxed=False)
-        self.assertEqual(s, 'ab')
+        assert s == 'ab'
 
     def test_strict_mount_point_names(self):
         s = self.f('1this+is.illegal', relaxed=False)
-        self.assertEqual(s, 'this-is-illegal')
+        assert s == 'this-is-illegal'
         s = self.f('this-1-is-legal', relaxed=False)
-        self.assertEqual(s, 'this-1-is-legal')
+        assert s == 'this-1-is-legal'
         s = self.f('THIS-IS-Illegal', relaxed=False)
-        self.assertEqual(s, 'this-is-illegal')
+        assert s == 'this-is-illegal'
 
     def test_relaxed_mount_point_names(self):
         s = self.f('1_this+is.legal')
-        self.assertEqual(s, '1_this+is.legal')
+        assert s == '1_this+is.legal'
         s = self.f('not*_legal')
-        self.assertEqual(s, 'not-legal')
+        assert s == 'not-legal'
         s = self.f('THIS-IS-Illegal')
-        self.assertEqual(s, 'THIS-IS-Illegal')
+        assert s == 'THIS-IS-Illegal'
 
 
 def test_escape_json():
@@ -593,7 +593,7 @@ class TestIterEntryPoints(TestCase):
     def test_disabled(self, pkg_resources):
         pkg_resources.iter_entry_points.return_value = [
             self._make_ep('myapp', object)]
-        self.assertEqual([], list(h.iter_entry_points('allura')))
+        assert [] == list(h.iter_entry_points('allura'))
 
     @patch('allura.lib.helpers.pkg_resources')
     def test_subclassed_ep(self, pkg_resources):
@@ -608,8 +608,8 @@ class TestIterEntryPoints(TestCase):
             self._make_ep('myapp', BetterApp)]
 
         eps = list(h.iter_entry_points('allura'))
-        self.assertEqual(len(eps), 1)
-        self.assertEqual(BetterApp, eps[0].load())
+        assert len(eps) == 1
+        assert BetterApp == eps[0].load()
 
     @patch('allura.lib.helpers.pkg_resources')
     def test_ambiguous_eps(self, pkg_resources):
diff --git a/Allura/allura/tests/test_markdown.py b/Allura/allura/tests/test_markdown.py
index cd74a9c45..f86506e6c 100644
--- a/Allura/allura/tests/test_markdown.py
+++ b/Allura/allura/tests/test_markdown.py
@@ -15,50 +15,46 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-import unittest
-
 import markdown
 import mock
 
 from allura.lib import markdown_extensions as mde
 
 
-class TestTracRef1(unittest.TestCase):
+class TestTracRef1:
 
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
     def test_no_such_artifact(self, lookup):
         lookup.return_value = None
-        self.assertEqual(mde.TracRef1().sub('#100'), '#100')
+        assert mde.TracRef1().sub('#100') == '#100'
 
     def test_skip_if_brackets(self):
-        self.assertEqual(mde.TracRef1().sub('[#100]'), '[#100]')
-        self.assertEqual(mde.TracRef1().sub('[r123]'), '[r123]')
+        assert mde.TracRef1().sub('[#100]') == '[#100]'
+        assert mde.TracRef1().sub('[r123]') == '[r123]'
 
     def test_word_boundaries(self):
-        self.assertEqual(mde.TracRef1().sub('foo#100'), 'foo#100')
-        self.assertEqual(mde.TracRef1().sub('r123bar'), 'r123bar')
+        assert mde.TracRef1().sub('foo#100') == 'foo#100'
+        assert mde.TracRef1().sub('r123bar') == 'r123bar'
 
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
     def test_legit_refs(self, lookup):
         shortlink = mock.Mock(url='/p/project/tool/artifact')
         shortlink.ref.artifact.deleted = False
         lookup.return_value = shortlink
-        self.assertEqual(mde.TracRef1().sub('#100'),
-                         '[#100](/p/project/tool/artifact)')
-        self.assertEqual(mde.TracRef1().sub('r123'),
-                         '[r123](/p/project/tool/artifact)')
+        assert mde.TracRef1().sub('#100') == '[#100](/p/project/tool/artifact)'
+        assert mde.TracRef1().sub('r123') == '[r123](/p/project/tool/artifact)'
 
 
-class TestTracRef2(unittest.TestCase):
+class TestTracRef2:
 
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
     def test_no_such_artifact(self, lookup):
         lookup.return_value = None
-        self.assertEqual(mde.TracRef2().sub('ticket:100'), 'ticket:100')
+        assert mde.TracRef2().sub('ticket:100') == 'ticket:100'
 
     def test_word_boundaries(self):
-        self.assertEqual(mde.TracRef2().sub('myticket:100'), 'myticket:100')
-        self.assertEqual(mde.TracRef2().sub('ticket:100th'), 'ticket:100th')
+        assert mde.TracRef2().sub('myticket:100') == 'myticket:100'
+        assert mde.TracRef2().sub('ticket:100th') == 'ticket:100th'
 
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
     def test_legit_refs(self, lookup):
@@ -67,36 +63,27 @@ class TestTracRef2(unittest.TestCase):
         lookup.return_value = shortlink
         pattern = mde.TracRef2()
         pattern.get_comment_slug = lambda *args: 'abc'
-        self.assertEqual(pattern.sub('ticket:100'),
-                         '[ticket:100](/p/project/tool/artifact/)')
-        self.assertEqual(pattern.sub('[ticket:100]'),
-                         '[[ticket:100](/p/project/tool/artifact/)]')
-        self.assertEqual(pattern.sub('comment:13:ticket:100'),
-                         '[comment:13:ticket:100](/p/project/tool/artifact/#abc)')
+        assert pattern.sub('ticket:100') == '[ticket:100](/p/project/tool/artifact/)'
+        assert pattern.sub('[ticket:100]') == '[[ticket:100](/p/project/tool/artifact/)]'
+        assert pattern.sub('comment:13:ticket:100') == '[comment:13:ticket:100](/p/project/tool/artifact/#abc)'
         pattern.get_comment_slug = lambda *args: None
-        self.assertEqual(pattern.sub('comment:13:ticket:100'),
-                         '[comment:13:ticket:100](/p/project/tool/artifact/)')
+        assert pattern.sub('comment:13:ticket:100') == '[comment:13:ticket:100](/p/project/tool/artifact/)'
 
 
-class TestTracRef3(unittest.TestCase):
+class TestTracRef3:
 
     def test_no_app_context(self):
-        self.assertEqual(mde.TracRef3(None)
-                         .sub('source:file.py'), 'source:file.py')
+        assert mde.TracRef3(None).sub('source:file.py') == 'source:file.py'
 
     def test_legit_refs(self):
         app = mock.Mock(url='/p/project/tool/')
-        self.assertEqual(mde.TracRef3(app).sub('source:file.py'),
-                         '[source:file.py](/p/project/tool/HEAD/tree/file.py)')
-        self.assertEqual(mde.TracRef3(app).sub('source:file.py@123'),
-                         '[source:file.py@123](/p/project/tool/123/tree/file.py)')
-        self.assertEqual(mde.TracRef3(app).sub('source:file.py@123#L456'),
-                         '[source:file.py@123#L456](/p/project/tool/123/tree/file.py#l456)')
-        self.assertEqual(mde.TracRef3(app).sub('source:file.py#L456'),
-                         '[source:file.py#L456](/p/project/tool/HEAD/tree/file.py#l456)')
+        assert mde.TracRef3(app).sub('source:file.py') == '[source:file.py](/p/project/tool/HEAD/tree/file.py)'
+        assert mde.TracRef3(app).sub('source:file.py@123') == '[source:file.py@123](/p/project/tool/123/tree/file.py)'
+        assert mde.TracRef3(app).sub('source:file.py@123#L456') == '[source:file.py@123#L456](/p/project/tool/123/tree/file.py#l456)'
+        assert mde.TracRef3(app).sub('source:file.py#L456') == '[source:file.py#L456](/p/project/tool/HEAD/tree/file.py#l456)'
 
 
-class TestPatternReplacingProcessor(unittest.TestCase):
+class TestPatternReplacingProcessor:
 
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
     def test_run(self, lookup):
@@ -105,12 +92,12 @@ class TestPatternReplacingProcessor(unittest.TestCase):
         lookup.return_value = shortlink
         p = mde.PatternReplacingProcessor(mde.TracRef1(), mde.TracRef2())
         res = p.run(['#100', 'ticket:100'])
-        self.assertEqual(res, [
+        assert res == [
             '[#100](/p/project/tool/artifact)',
-            '[ticket:100](/p/project/tool/artifact)'])
+            '[ticket:100](/p/project/tool/artifact)']
 
 
-class TestCommitMessageExtension(unittest.TestCase):
+class TestCommitMessageExtension:
 
     @mock.patch('allura.lib.markdown_extensions.TracRef2.get_comment_slug')
     @mock.patch('allura.lib.markdown_extensions.M.Shortlink.lookup')
@@ -145,4 +132,4 @@ Not *strong* or _underlined_."""
         md = markdown.Markdown(
             extensions=[mde.CommitMessageExtension(app), 'markdown.extensions.nl2br'],
             output_format='html')
-        self.assertEqual(md.convert(text), expected_html)
+        assert md.convert(text) == expected_html
\ No newline at end of file
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index fbe721b7d..4497f9c3c 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -48,18 +48,18 @@ class TestConfigProxy(unittest.TestCase):
         self.cp = utils.ConfigProxy(mybaz="baz")
 
     def test_getattr(self):
-        self.assertEqual(self.cp.foo, "bar")
-        self.assertEqual(self.cp.mybaz, "true")
+        assert self.cp.foo == "bar"
+        assert self.cp.mybaz == "true"
 
     def test_get(self):
-        self.assertEqual(self.cp.get("foo"), "bar")
-        self.assertEqual(self.cp.get("mybaz"), "true")
-        self.assertEqual(self.cp.get("fake"), None)
-        self.assertEqual(self.cp.get("fake", "default"), "default")
+        assert self.cp.get("foo") == "bar"
+        assert self.cp.get("mybaz") == "true"
+        assert self.cp.get("fake") is None
+        assert self.cp.get("fake", "default") == "default"
 
     def test_get_bool(self):
-        self.assertEqual(self.cp.get_bool("mybaz"), True)
-        self.assertEqual(self.cp.get_bool("fake"), False)
+        assert self.cp.get_bool("mybaz") is True
+        assert self.cp.get_bool("fake") is False
 
 
 class TestChunkedIterator(unittest.TestCase):
@@ -75,8 +75,8 @@ class TestChunkedIterator(unittest.TestCase):
 
     def test_can_iterate(self):
         chunks = list(utils.chunked_find(M.User, {}, 2))
-        assert len(chunks) > 1, chunks
-        assert len(chunks[0]) == 2, chunks[0]
+        assert len(chunks) > 1
+        assert len(chunks[0]) == 2
 
     def test_filter_on_sort_key(self):
         query = {'username':
@@ -85,9 +85,9 @@ class TestChunkedIterator(unittest.TestCase):
                                          query,
                                          2,
                                          sort_key='username'))
-        assert len(chunks) == 2, chunks
-        assert len(chunks[0]) == 2, chunks[0]
-        assert len(chunks[1]) == 1, chunks[1]
+        assert len(chunks) == 2
+        assert len(chunks[0]) == 2
+        assert len(chunks[1]) == 1
         assert chunks[0][0].username == 'sample-user-1'
         assert chunks[0][1].username == 'sample-user-2'
         assert chunks[1][0].username == 'sample-user-3'
@@ -98,9 +98,9 @@ class TestChunkedList(unittest.TestCase):
     def test_chunked_list(self):
         l = list(range(10))
         chunks = list(utils.chunked_list(l, 3))
-        self.assertEqual(len(chunks), 4)
-        self.assertEqual(len(chunks[0]), 3)
-        self.assertEqual([el for sublist in chunks for el in sublist], l)
+        assert len(chunks) == 4
+        assert len(chunks[0]) == 3
+        assert [el for sublist in chunks for el in sublist] == l
 
 
 class TestAntispam(unittest.TestCase):
@@ -111,9 +111,9 @@ class TestAntispam(unittest.TestCase):
 
     def test_generate_fields(self):
         fields = '\n'.join(self.a.extra_fields())
-        assert 'name="timestamp"' in fields, fields
-        assert 'name="spinner"' in fields, fields
-        assert ('class="%s"' % self.a.honey_class) in fields, fields
+        assert 'name="timestamp"' in fields
+        assert 'name="spinner"' in fields
+        assert ('class="%s"' % self.a.honey_class) in fields
 
     def test_invalid_old(self):
         form = dict(a='1', b='2')
@@ -127,7 +127,7 @@ class TestAntispam(unittest.TestCase):
                           environ={'remote_addr': '127.0.0.1'}
                           )
         validated = utils.AntiSpam.validate_request(r)
-        assert dict(a='1', b='2') == validated, validated
+        assert dict(a='1', b='2') == validated
 
     def test_invalid_future(self):
         form = dict(a='1', b='2')
@@ -178,7 +178,7 @@ class TestCaseInsensitiveDict(unittest.TestCase):
         d['bar'] = 7
         assert d['bar'] == d['bAr'] == 7
         del d['bar']
-        assert len(d) == 1, d
+        assert len(d) == 1
         assert d.get('foo') == 5
         d.update(foo=1, Bar=2)
         assert d.get('FOO') == 1
@@ -291,8 +291,7 @@ def test_ip_address():
     req = Mock()
     req.remote_addr = '1.2.3.4'
     req.headers = {}
-    assert (utils.ip_address(req) ==
-            '1.2.3.4')
+    assert utils.ip_address(req) == '1.2.3.4'
 
 
 def test_ip_address_header():
@@ -300,8 +299,7 @@ def test_ip_address_header():
     req.remote_addr = '1.2.3.4'
     req.headers = {'X_FORWARDED_FOR': '5.6.7.8'}
     with h.push_config(config, **{'ip_address_header': 'X_FORWARDED_FOR'}):
-        assert (utils.ip_address(req) ==
-                '5.6.7.8')
+        assert utils.ip_address(req) == '5.6.7.8'
 
 
 def test_ip_address_header_not_set():
@@ -309,8 +307,7 @@ def test_ip_address_header_not_set():
     req.remote_addr = '1.2.3.4'
     req.headers = {}
     with h.push_config(config, **{'ip_address_header': 'X_FORWARDED_FOR'}):
-        assert (utils.ip_address(req) ==
-                '1.2.3.4')
+        assert utils.ip_address(req) == '1.2.3.4'
 
 
 def test_empty_cursor():
@@ -338,7 +335,7 @@ def test_DateJSONEncoder():
             'date': dt.datetime(2015, 1, 30, 13, 13, 13)}
     result = json.dumps(data, cls=utils.DateJSONEncoder)
     assert result in ['{"date": "2015-01-30T13:13:13Z", "message": "Hi!"}',
-                      '{"message": "Hi!", "date": "2015-01-30T13:13:13Z"}'], result
+                      '{"message": "Hi!", "date": "2015-01-30T13:13:13Z"}']
 
 
 def test_clean_phone_number():
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index a290be4f4..cf9bca102 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -42,7 +42,7 @@ class TestJsonConverter(unittest.TestCase):
         _setup_method()
 
     def test_valid(self):
-        self.assertEqual({}, self.val.to_python('{}'))
+        assert {} == self.val.to_python('{}')
 
     def test_invalid(self):
         with self.assertRaises(fe.Invalid):
@@ -64,7 +64,7 @@ class TestJsonFile(unittest.TestCase):
             self.value = content
 
     def test_valid(self):
-        self.assertEqual({}, self.val.to_python(self.FieldStorage('{}')))
+        assert {} == self.val.to_python(self.FieldStorage('{}'))
 
     def test_invalid(self):
         with self.assertRaises(fe.Invalid):
@@ -83,8 +83,8 @@ class TestUserMapFile(unittest.TestCase):
             self.value = content
 
     def test_valid(self):
-        self.assertEqual({"user_old": "user_new"}, self.val.to_python(
-            self.FieldStorage('{"user_old": "user_new"}')))
+        assert {"user_old": "user_new"} == self.val.to_python(
+            self.FieldStorage('{"user_old": "user_new"}'))
 
     def test_invalid(self):
         with self.assertRaises(fe.Invalid):
@@ -92,8 +92,8 @@ class TestUserMapFile(unittest.TestCase):
 
     def test_as_string(self):
         val = v.UserMapJsonFile(as_string=True)
-        self.assertEqual('{"user_old": "user_new"}', val.to_python(
-            self.FieldStorage('{"user_old": "user_new"}')))
+        assert '{"user_old": "user_new"}' == val.to_python(
+            self.FieldStorage('{"user_old": "user_new"}'))
 
 
 class TestUserValidator(unittest.TestCase):
@@ -103,13 +103,12 @@ class TestUserValidator(unittest.TestCase):
         _setup_method()
 
     def test_valid(self):
-        self.assertEqual(M.User.by_username('root'),
-                         self.val.to_python('root'))
+        assert M.User.by_username('root') == self.val.to_python('root')
 
     def test_invalid(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('fakeuser')
-        self.assertEqual(str(cm.exception), "Invalid username")
+        assert str(cm.exception) == "Invalid username"
 
 
 class TestAnonymousValidator(unittest.TestCase):
@@ -121,14 +120,14 @@ class TestAnonymousValidator(unittest.TestCase):
     @patch('allura.lib.validators.c')
     def test_valid(self, c):
         c.user = M.User.by_username('root')
-        self.assertEqual(True, self.val.to_python(True))
+        assert self.val.to_python(True)
 
     @patch('allura.lib.validators.c')
     def test_invalid(self, c):
         c.user = M.User.anonymous()
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python(True)
-        self.assertEqual(str(cm.exception), "Log in to Mark as Private")
+        assert str(cm.exception) ==  "Log in to Mark as Private"
 
 
 class TestMountPointValidator(unittest.TestCase):
@@ -143,7 +142,7 @@ class TestMountPointValidator(unittest.TestCase):
         App.validate_mount_point.return_value = True
         c.project.app_instance.return_value = None
         val = v.MountPointValidator(App)
-        self.assertEqual('mymount', val.to_python('Mymount'))
+        assert 'mymount' == val.to_python('Mymount')
 
     @patch('allura.lib.validators.c')
     def test_invalid(self, c):
@@ -162,7 +161,7 @@ class TestMountPointValidator(unittest.TestCase):
         App.validate_mount_point.return_value = True
         c.project.app_instance.return_value = None
         val = v.MountPointValidator(App)
-        self.assertEqual('Mymount', val.to_python('Mymount'))
+        assert 'Mymount' == val.to_python('Mymount')
 
     @patch('allura.lib.validators.c')
     def test_in_use(self, c):
@@ -190,8 +189,8 @@ class TestMountPointValidator(unittest.TestCase):
         App.default_mount_point = 'wiki'
         c.project.app_instance.side_effect = lambda mp: None if mp != 'wiki' else True
         val = v.MountPointValidator(App)
-        self.assertEqual('wiki-0', val.to_python(''))
-        self.assertEqual('wiki-0', val.to_python(None))
+        assert 'wiki-0' == val.to_python('')
+        assert 'wiki-0' == val.to_python(None)
 
 
 class TestTaskValidator(unittest.TestCase):
@@ -201,8 +200,7 @@ class TestTaskValidator(unittest.TestCase):
         _setup_method()
 
     def test_valid(self):
-        self.assertEqual(
-            dummy_task, self.val.to_python('allura.tests.test_validators.dummy_task'))
+        assert dummy_task == self.val.to_python('allura.tests.test_validators.dummy_task')
 
     def test_invalid_name(self):
         with self.assertRaises(fe.Invalid) as cm:
@@ -212,19 +210,17 @@ class TestTaskValidator(unittest.TestCase):
     def test_import_failure(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('allura.does.not.exist')
-        self.assertEqual(str(cm.exception),
-                         'Could not import "allura.does.not.exist"')
+        assert str(cm.exception) =='Could not import "allura.does.not.exist"'
 
     def test_attr_lookup_failure(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('allura.tests.test_validators.typo')
-        self.assertEqual(str(cm.exception), 'Module has no attribute "typo"')
+        assert str(cm.exception) == 'Module has no attribute "typo"'
 
     def test_not_a_task(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('allura.tests.test_validators._setup_method')
-        self.assertEqual(str(cm.exception),
-                         '"allura.tests.test_validators._setup_method" is not a task.')
+        assert str(cm.exception) == '"allura.tests.test_validators._setup_method" is not a task.'
 
 
 class TestPathValidator(unittest.TestCase):
@@ -236,22 +232,22 @@ class TestPathValidator(unittest.TestCase):
     def test_valid_project(self):
         project = M.Project.query.get(shortname='test')
         d = self.val.to_python('/p/test')
-        self.assertEqual(d['project'], project)
+        assert d['project'] == project
         assert 'app' not in d
 
     def test_project_in_nbhd_with_prefix(self):
         create_user('myuser', make_project=True)
         project = M.Project.query.get(shortname='u/myuser')
         d = self.val.to_python('/u/myuser')
-        self.assertEqual(d['project'], project)
+        assert d['project'] == project
         assert 'app' not in d
 
     def test_valid_app(self):
         project = M.Project.query.get(shortname='test')
         app = project.app_instance('admin')
         d = self.val.to_python('/p/test/admin/')
-        self.assertEqual(d['project'], project)
-        self.assertEqual(d['app'].config._id, app.config._id)
+        assert d['project'] == project
+        assert d['app'].config._id == app.config._id
 
     def test_invalid_format(self):
         with self.assertRaises(fe.Invalid) as cm:
@@ -262,20 +258,20 @@ class TestPathValidator(unittest.TestCase):
     def test_invalid_neighborhood(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('/q/test')
-        self.assertEqual(str(cm.exception), 'Invalid neighborhood: /q/')
+        assert str(cm.exception) == 'Invalid neighborhood: /q/'
 
     def test_invalid_project(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('/p/badproject')
-        self.assertEqual(str(cm.exception), 'Invalid project: badproject')
+        assert str(cm.exception) == 'Invalid project: badproject'
 
     def test_invalid_app_mount_point(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('/p/test/badapp')
-        self.assertEqual(str(cm.exception), 'Invalid app mount point: badapp')
+        assert str(cm.exception) == 'Invalid app mount point: badapp'
 
     def test_no_input(self):
-        self.assertEqual({}, self.val.to_python(''))
+        assert {} == self.val.to_python('')
 
 
 class TestUrlValidator(unittest.TestCase):
@@ -285,18 +281,18 @@ class TestUrlValidator(unittest.TestCase):
         _setup_method()
 
     def test_valid(self):
-        self.assertEqual('http://192.168.0.1', self.val.to_python('192.168.0.1'))
-        self.assertEqual('http://url', self.val.to_python('url'))
+        assert 'http://192.168.0.1' == self.val.to_python('192.168.0.1')
+        assert 'http://url' == self.val.to_python('url')
 
     def test_invalid_ip(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('192.168.0')
-        self.assertEqual(str(cm.exception), 'That is not a valid URL')
+        assert str(cm.exception) == 'That is not a valid URL'
 
     def test_invalid_url(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('u"rl')
-        self.assertEqual(str(cm.exception), 'That is not a valid URL')
+        assert str(cm.exception) == 'That is not a valid URL'
 
 
 class TestNonHttpUrlValidator(unittest.TestCase):
@@ -306,18 +302,18 @@ class TestNonHttpUrlValidator(unittest.TestCase):
         _setup_method()
 
     def test_valid(self):
-        self.assertEqual('svn://192.168.0.1', self.val.to_python('svn://192.168.0.1'))
-        self.assertEqual('ssh+git://url', self.val.to_python('ssh+git://url'))
+        assert 'svn://192.168.0.1' == self.val.to_python('svn://192.168.0.1')
+        assert 'ssh+git://url' == self.val.to_python('ssh+git://url')
 
     def test_invalid(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('http://u"rl')
-        self.assertEqual(str(cm.exception), 'That is not a valid URL')
+        assert str(cm.exception) == 'That is not a valid URL'
 
     def test_no_scheme(self):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('url')
-        self.assertEqual(str(cm.exception), 'You must start your URL with a scheme')
+        assert str(cm.exception) == 'You must start your URL with a scheme'
 
 
 class TestIconValidator(unittest.TestCase):
@@ -333,21 +329,21 @@ class TestIconValidator(unittest.TestCase):
 
     def test_valid(self):
         input = self._mock('foo.png')
-        self.assertEqual(input, self.val.to_python(input))
+        assert input  == self.val.to_python(input)
 
         input = self._mock('foo.jpg')
-        self.assertEqual(input, self.val.to_python(input))
+        assert input == self.val.to_python(input)
 
         input = self._mock('svg.jpg')
-        self.assertEqual(input, self.val.to_python(input))
+        assert input == self.val.to_python(input)
 
     def test_invalid(self):
         input = self._mock('foo.svg')
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python(input)
-        self.assertEqual(str(cm.exception), 'Project icons must be PNG, GIF, JPG, or BMP format.')
+        assert str(cm.exception) == 'Project icons must be PNG, GIF, JPG, or BMP format.'
 
         input = self._mock('foogif.svg')
         with self.assertRaises(fe.Invalid) as cm:
-            self.assertEqual(input, self.val.to_python(input))
-        self.assertEqual(str(cm.exception), 'Project icons must be PNG, GIF, JPG, or BMP format.')
+            assert input == self.val.to_python(input)
+        assert str(cm.exception) == 'Project icons must be PNG, GIF, JPG, or BMP format.'
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 18b7eafec..ba31a5c9d 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -1,21 +1,4 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-from unittest import TestCase
+import pytest
 
 from allura.app import Application
 from allura import model
@@ -25,58 +8,65 @@ from allura.tests.unit.patches import fake_app_patch
 from allura.tests.unit.factories import create_project, create_app_config
 
 
-class TestApplication(TestCase):
+def test_validate_mount_point():
+    app = Application
 
-    def test_validate_mount_point(self):
-        app = Application
+    assert app.validate_mount_point('dash-in-middle') is not None
+    assert app.validate_mount_point('end-dash-') is None
 
-        self.assertIsNotNone(app.validate_mount_point('dash-in-middle'))
+    mount_point = '1.2+foo_bar'
+    assert app.validate_mount_point(mount_point) is None
 
-        self.assertIsNone(app.validate_mount_point('end-dash-'))
+    with h.push_config(app, relaxed_mount_points=True):
+        assert app.validate_mount_point(mount_point) is not None
 
-        mount_point = '1.2+foo_bar'
-        self.assertIsNone(app.validate_mount_point(mount_point))
 
-        with h.push_config(app, relaxed_mount_points=True):
-            self.assertIsNotNone(app.validate_mount_point(mount_point))
+def test_describe_permission():
+    class DummyApp(Application):
+        permissions_desc = {
+            'foo': 'bar',
+            'post': 'overridden',
+        }
+    f = DummyApp.describe_permission
+    assert f('foo') == 'bar'
+    assert f('post') == 'overridden'
+    assert f('admin') == 'Set permissions.'
+    assert f('does_not_exist') == ''
 
-    def test_describe_permission(self):
-        class DummyApp(Application):
-            permissions_desc = {
-                'foo': 'bar',
-                'post': 'overridden',
-            }
-        f = DummyApp.describe_permission
-        self.assertEqual(f('foo'), 'bar')
-        self.assertEqual(f('post'), 'overridden')
-        self.assertEqual(f('admin'), 'Set permissions.')
-        self.assertEqual(f('does_not_exist'), '')
+
+@pytest.fixture
+def installed_app(request):
+    """Returns an installed application instance."""
+    project = create_project('myproject')
+    app_config = create_app_config(project, 'my_mounted_app')
+    app = Application(project, app_config)
+    app.install(project)
+    return app
 
 
 class TestInstall(WithDatabase):
     patches = [fake_app_patch]
 
     def test_that_it_creates_a_discussion(self):
-        original_discussion_count = self.discussion_count()
-        install_app()
-        assert self.discussion_count() == original_discussion_count + 1
+        def discussion_count():
+            return model.Discussion.query.find().count()
 
-    def discussion_count(self):
-        return model.Discussion.query.find().count()
+        original_discussion_count = discussion_count()
+        install_app()
+        assert discussion_count() == original_discussion_count + 1
 
 
 class TestDefaultDiscussion(WithDatabase):
     patches = [fake_app_patch]
 
-    def setup_method(self, method):
-        super().setup_method(method)
+    @pytest.fixture(autouse=True)
+    def setup_discussion(self):
         install_app()
         self.discussion = model.Discussion.query.get(
             shortname='my_mounted_app')
 
     def test_that_it_has_a_description(self):
-        description = self.discussion.description
-        assert description == 'Forum for my_mounted_app comments'
+        assert self.discussion.description == 'Forum for my_mounted_app comments'
 
     def test_that_it_has_a_name(self):
         assert self.discussion.name == 'my_mounted_app Discussion'
@@ -88,8 +78,8 @@ class TestDefaultDiscussion(WithDatabase):
 class TestAppDefaults(WithDatabase):
     patches = [fake_app_patch]
 
-    def setup_method(self, method):
-        super().setup_method(method)
+    @pytest.fixture(autouse=True)
+    def setup_app(self):
         self.app = install_app()
 
     def test_that_it_has_an_empty_sidebar_menu(self):
@@ -111,9 +101,10 @@ class TestAppDefaults(WithDatabase):
 
 
 def install_app():
+    """Helper function to create and install an application instance."""
     project = create_project('myproject')
     app_config = create_app_config(project, 'my_mounted_app')
     # XXX: Remove project argument to install; it's redundant
     app = Application(project, app_config)
     app.install(project)
-    return app
+    return app
\ No newline at end of file
diff --git a/Allura/allura/tests/unit/test_artifact.py b/Allura/allura/tests/unit/test_artifact.py
index 895eb74ec..590cb2d32 100644
--- a/Allura/allura/tests/unit/test_artifact.py
+++ b/Allura/allura/tests/unit/test_artifact.py
@@ -26,4 +26,4 @@ class TestArtifact(unittest.TestCase):
         fields = {'name_t': '', 'shortname_s': ''}
         query = 'name:1 AND shortname:2 AND shortname_name_field:3'
         q = M.Artifact.translate_query(query, fields)
-        self.assertEqual(q, 'name_t:1 AND shortname_s:2 AND shortname_name_field:3')
+        assert q  == 'name_t:1 AND shortname_s:2 AND shortname_name_field:3'
diff --git a/Allura/allura/tests/unit/test_project.py b/Allura/allura/tests/unit/test_project.py
index 3f6acc8b2..01113b2b5 100644
--- a/Allura/allura/tests/unit/test_project.py
+++ b/Allura/allura/tests/unit/test_project.py
@@ -50,8 +50,8 @@ class TestProject(unittest.TestCase):
         ]
         expected_ticket_urls = ['bugs url', 'features url', 'support url']
         actual = [(e.label, e.url, len(e.matching_urls)) for e in entries]
-        self.assertEqual(expected, actual)
-        self.assertEqual(entries[0].matching_urls, expected_ticket_urls)
+        assert expected == actual
+        assert entries[0].matching_urls == expected_ticket_urls
 
     def test_grouped_navbar_threshold(self):
         p = M.Project()
@@ -78,17 +78,16 @@ class TestProject(unittest.TestCase):
         ]
         expected_ticket_urls = ['bugs url', 'features url', 'support url']
         actual = [(e.label, e.url, len(e.matching_urls)) for e in entries]
-        self.assertEqual(expected, actual)
-        self.assertEqual(entries[0].matching_urls, expected_ticket_urls)
+        assert expected == actual
+        assert entries[0].matching_urls == expected_ticket_urls
 
     def test_social_account(self):
         p = M.Project()
         self.assertIsNone(p.social_account('Twitter'))
 
         p.set_social_account('Twitter', 'http://twitter.com/allura')
-        self.assertEqual(p.social_account('Twitter')
-                         .accounturl, 'http://twitter.com/allura')
-        self.assertEqual(p.twitter_handle, 'http://twitter.com/allura')
+        assert p.social_account('Twitter').accounturl == 'http://twitter.com/allura'
+        assert p.twitter_handle == 'http://twitter.com/allura'
 
     def test_should_update_index(self):
         p = M.Project()
@@ -108,7 +107,7 @@ class TestProject(unittest.TestCase):
             shortname='myproj',
             neighborhood=M.Neighborhood(url_prefix='/nbhd/'),
         )
-        self.assertEqual(p.icon_url(), '/nbhd/myproj/icon')
+        assert p.icon_url() == '/nbhd/myproj/icon'
 
         with h.push_config(config, **{'static.icon_base': 'https://mycdn.com/mysite'}):
-            self.assertEqual(p.icon_url(), 'https://mycdn.com/mysite/nbhd/myproj/icon')
+            assert p.icon_url() == 'https://mycdn.com/mysite/nbhd/myproj/icon'
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index db0b32c2e..2459ad032 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -60,8 +60,7 @@ class TestTopoSort(unittest.TestCase):
             'master':     datetime.datetime(2012, 5, 1),
             'dev':        datetime.datetime(2012, 6, 1)}
         result = topo_sort(children, parents, dates, head_ids)
-        self.assertEqual(list(result), ['dev', 'dev@{1}', 'master',
-                                        'master@{1}', 'master@{2}', 'master@{3}'])
+        assert list(result) == ['dev', 'dev@{1}', 'master', 'master@{1}', 'master@{2}', 'master@{3}']
 
 
 def tree(name, id, trees=None, blobs=None):
@@ -146,8 +145,8 @@ class TestCommit(unittest.TestCase):
         commit = M.repository.Commit()
         commit.shorthand_id = MagicMock(return_value='abcdef')
         commit.message = 'commit msg'
-        self.assertIn('allura_id', commit.activity_extras)
-        self.assertEqual(commit.activity_extras['summary'], commit.summary)
+        assert 'allura_id' in commit.activity_extras
+        assert commit.activity_extras['summary'] == commit.summary
 
     def test_get_path_no_create(self):
         commit = M.repository.Commit()
@@ -155,7 +154,7 @@ class TestCommit(unittest.TestCase):
         commit.get_path('foo/', create=False)
         commit.get_tree.assert_called_with(False)
         commit.get_tree().__getitem__.assert_called_with('foo')
-        self.assertNotIn(call(''), commit.get_tree().__getitem__.call_args_list)
+        assert (call('') not in commit.get_tree().__getitem__.call_args_list)
 
     def test_get_tree_no_create(self):
         c.model_cache = Mock()
@@ -275,10 +274,10 @@ class TestZipDir(unittest.TestCase):
         with self.assertRaises(Exception) as cm:
             zipdir(src, zipfile)
         emsg = str(cm.exception)
-        self.assertIn(
-            "Command: " +
-            "['/bin/zip', '-y', '-q', '-r', '/fake/zip/file.tmp', b'repo'] " +
-            "returned non-zero exit code 1", emsg)
+        assert \
+            "Command: " + \
+            "['/bin/zip', '-y', '-q', '-r', '/fake/zip/file.tmp', b'repo'] " + \
+            "returned non-zero exit code 1" in emsg
         assert "STDOUT: 1" in emsg
         assert "STDERR: 2" in emsg
 
@@ -288,17 +287,17 @@ class TestPrefixPathsUnion(unittest.TestCase):
     def test_disjoint(self):
         a = {'a1', 'a2', 'a3'}
         b = {'b1', 'b1/foo', 'b2'}
-        self.assertEqual(prefix_paths_union(a, b), set())
+        assert prefix_paths_union(a, b) == set()
 
     def test_exact(self):
         a = {'a1', 'a2', 'a3'}
         b = {'b1', 'a2', 'a3'}
-        self.assertEqual(prefix_paths_union(a, b), {'a2', 'a3'})
+        assert prefix_paths_union(a, b) == {'a2', 'a3'}
 
     def test_prefix(self):
         a = {'a1', 'a2', 'a3'}
         b = {'b1', 'a2/foo', 'b3/foo'}
-        self.assertEqual(prefix_paths_union(a, b), {'a2'})
+        assert prefix_paths_union(a, b) == {'a2'}
 
 
 class TestGroupCommits:
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index 282b5678e..bc3463f3e 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -167,17 +167,17 @@ class TestBatchIndexer(TestCase):
         arefs = [m(_id=i) for i in (4, 5, 6)]
         find.return_value = [m(_id=i) for i in (7, 8, 9)]
         self.ext.update_index(objs_deleted, arefs)
-        self.assertEqual(self.ext.to_delete,
-                         {o.index_id() for o in objs_deleted})
-        self.assertEqual(self.ext.to_add, {4, 5, 6})
+        assert self.ext.to_delete == \
+                         {o.index_id() for o in objs_deleted}
+        assert self.ext.to_add == {4, 5, 6}
 
         # test deleting something that was previously added
         objs_deleted += [m(_id=4)]
         find.return_value = [m(_id=4)]
         self.ext.update_index(objs_deleted, [])
-        self.assertEqual(self.ext.to_delete,
-                         {o.index_id() for o in objs_deleted})
-        self.assertEqual(self.ext.to_add, {5, 6})
+        assert self.ext.to_delete == \
+                         {o.index_id() for o in objs_deleted}
+        assert self.ext.to_add == {5, 6}
 
     @mock.patch('allura.model.session.index_tasks')
     def test_flush(self, index_tasks):
@@ -189,34 +189,32 @@ class TestBatchIndexer(TestCase):
         index_tasks.del_artifacts.post.assert_called_once_with(
             list(del_index_ids))
         index_tasks.add_artifacts.post.assert_called_once_with([4, 5, 6])
-        self.assertEqual(self.ext.to_delete, set())
-        self.assertEqual(self.ext.to_add, set())
+        assert self.ext.to_delete == set()
+        assert self.ext.to_add == set()
 
     @mock.patch('allura.model.session.index_tasks')
     def test_flush_chunks_huge_lists(self, index_tasks):
         self.extcls.to_delete = set(range(100 * 1000 + 1))
         self.extcls.to_add = set(range(1000 * 1000 + 1))
         self.ext.flush()
-        self.assertEqual(
-            len(index_tasks.del_artifacts.post.call_args_list[0][0][0]),
-            100 * 1000)
-        self.assertEqual(
-            len(index_tasks.del_artifacts.post.call_args_list[1][0][0]), 1)
-        self.assertEqual(
-            len(index_tasks.add_artifacts.post.call_args_list[0][0][0]),
-            1000 * 1000)
-        self.assertEqual(
-            len(index_tasks.add_artifacts.post.call_args_list[1][0][0]), 1)
-        self.assertEqual(self.ext.to_delete, set())
-        self.assertEqual(self.ext.to_add, set())
+        assert \
+            len(index_tasks.del_artifacts.post.call_args_list[0][0][0]) == 100 * 1000
+        assert \
+            len(index_tasks.del_artifacts.post.call_args_list[1][0][0]) == 1
+        assert \
+            len(index_tasks.add_artifacts.post.call_args_list[0][0][0]) == 1000 * 1000
+        assert \
+            len(index_tasks.add_artifacts.post.call_args_list[1][0][0]) == 1
+        assert self.ext.to_delete == set()
+        assert self.ext.to_add == set()
 
     @mock.patch('allura.tasks.index_tasks')
     def test_flush_noop(self, index_tasks):
         self.ext.flush()
-        self.assertEqual(0, index_tasks.del_artifacts.post.call_count)
-        self.assertEqual(0, index_tasks.add_artifacts.post.call_count)
-        self.assertEqual(self.ext.to_delete, set())
-        self.assertEqual(self.ext.to_add, set())
+        assert 0 == index_tasks.del_artifacts.post.call_count
+        assert 0 == index_tasks.add_artifacts.post.call_count
+        assert self.ext.to_delete == set()
+        assert self.ext.to_add == set()
 
     @mock.patch('allura.tasks.index_tasks')
     def test__post_too_large(self, index_tasks):
@@ -240,8 +238,8 @@ class TestBatchIndexer(TestCase):
             mock.call([3]),
             mock.call([4])
         ]
-        self.assertEqual(
-            expected, index_tasks.add_artifacts.post.call_args_list)
+        assert \
+            expected == index_tasks.add_artifacts.post.call_args_list
 
     @mock.patch('allura.tasks.index_tasks')
     def test__post_other_error(self, index_tasks):
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 3a61c6869..aad27253f 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -210,9 +210,9 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
             os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive'))[0] & stat.S_IXUSR
         with open(os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) as f:
             c = f.read()
-        self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n', c)
-        self.assertIn('exec $DIR/post-receive-user\n', c)
+        assert \
+            'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n' in c
+        assert 'exec $DIR/post-receive-user\n' in c
         shutil.rmtree(dirname)
 
     @mock.patch('forgegit.model.git_repo.git.Repo.clone_from', autospec=True)
@@ -244,9 +244,9 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
                 os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive'))[0] & stat.S_IXUSR
             with open(os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) as f:
                 c = f.read()
-            self.assertIn(
-                'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n', c)
-            self.assertIn('exec $DIR/post-receive-user\n', c)
+            assert \
+                'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n' in c
+            assert 'exec $DIR/post-receive-user\n' in c
             shutil.rmtree(dirname)
 
     def test_index(self):
@@ -365,10 +365,10 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         # regenerate the tree
         new_tree = entry.tree
         assert new_tree
-        self.assertEqual(new_tree._id, orig_tree._id)
-        self.assertEqual(new_tree.tree_ids, orig_tree.tree_ids)
-        self.assertEqual(new_tree.blob_ids, orig_tree.blob_ids)
-        self.assertEqual(new_tree.other_ids, orig_tree.other_ids)
+        assert new_tree._id == orig_tree._id
+        assert new_tree.tree_ids == orig_tree.tree_ids
+        assert new_tree.blob_ids == orig_tree.blob_ids
+        assert new_tree.other_ids == orig_tree.other_ids
 
     def test_refresh(self):
         # test results of things that ran during setup_method
@@ -513,16 +513,16 @@ By Dave Brondsema''' in text_body
             '1e146e67985dcd71c74de79613719bef7bddca4a',  # master
             '5c47243c8e424136fd5cdd18cd94d34c66d1955c',  # zz
         ]
-        self.assertIn(cids[0], heads)  # repo head comes first
+        assert cids[0] in heads  # repo head comes first
         for head in heads:
-            self.assertIn(head, cids)  # all branches included
+            assert head in cids  # all branches included
         # repo root comes last
-        self.assertEqual(cids[-1], '9a7df788cf800241e3bb5a849c8870f2f8259d98')
+        assert cids[-1] == '9a7df788cf800241e3bb5a849c8870f2f8259d98'
 
     def test_ls(self):
         c.lcid_cache = {}  # else it'll be a mock
         lcd_map = self.repo.commit('HEAD').tree.ls()
-        self.assertEqual(lcd_map, [{
+        assert lcd_map == [{
             'href': 'README',
             'kind': 'BLOB',
             'last_commit': {
@@ -533,7 +533,7 @@ By Dave Brondsema''' in text_body
                 'href': '/p/test/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/',
                 'shortlink': '[1e146e]',
                 'summary': 'Change README'},
-            'name': 'README'}])
+            'name': 'README'}]
 
     def test_ls_with_prev(self):
         c.lcid_cache = {}  # else it'll be a mock
@@ -993,12 +993,12 @@ class TestGitImplementation(unittest.TestCase):
         repo.__ming__ = mock.Mock()
         repo.cached_branches = []
         impl = GM.git_repo.GitImplementation(repo)
-        self.assertEqual(impl.branches, [
+        assert impl.branches == [
             Object(name='master',
                    object_id='1e146e67985dcd71c74de79613719bef7bddca4a'),
             Object(name='zz',
                    object_id='5c47243c8e424136fd5cdd18cd94d34c66d1955c')
-        ])
+        ]
 
     def test_tags(self):
         repo_dir = pkg_resources.resource_filename(
@@ -1007,10 +1007,10 @@ class TestGitImplementation(unittest.TestCase):
         repo.__ming__ = mock.Mock()
         repo.cached_tags = []
         impl = GM.git_repo.GitImplementation(repo)
-        self.assertEqual(impl.tags, [
+        assert impl.tags == [
             Object(name='foo',
                    object_id='1e146e67985dcd71c74de79613719bef7bddca4a'),
-        ])
+        ]
 
     def test_last_commit_ids(self):
         repo_dir = pkg_resources.resource_filename(
@@ -1018,13 +1018,13 @@ class TestGitImplementation(unittest.TestCase):
         repo = mock.Mock(full_fs_path=repo_dir)
         impl = GM.git_repo.GitImplementation(repo)
         def lcd(c, p): return impl.last_commit_ids(mock.Mock(_id=c), p)
-        self.assertEqual(lcd('13951944969cf45a701bf90f83647b309815e6d5', ['f2.txt', 'f3.txt']), {
+        assert lcd('13951944969cf45a701bf90f83647b309815e6d5', ['f2.txt', 'f3.txt']) == {
             'f2.txt': '259c77dd6ee0e6091d11e429b56c44ccbf1e64a3',
             'f3.txt': '653667b582ef2950c1954a0c7e1e8797b19d778a',
-        })
-        self.assertEqual(lcd('259c77dd6ee0e6091d11e429b56c44ccbf1e64a3', ['f2.txt', 'f3.txt']), {
+        }
+        assert lcd('259c77dd6ee0e6091d11e429b56c44ccbf1e64a3', ['f2.txt', 'f3.txt']) == {
             'f2.txt': '259c77dd6ee0e6091d11e429b56c44ccbf1e64a3',
-        })
+        }
 
     def test_last_commit_ids_threaded(self):
         with h.push_config(tg.config, lcd_thread_chunk_size=1):
@@ -1040,7 +1040,7 @@ class TestGitImplementation(unittest.TestCase):
             impl = GM.git_repo.GitImplementation(repo)
             lcds = impl.last_commit_ids(
                 mock.Mock(_id='13951944969cf45a701bf90f83647b309815e6d5'), ['f2.txt', 'f3.txt'])
-            self.assertEqual(lcds, {})
+            assert lcds == {}
 
 
 class TestGitCommit(unittest.TestCase):
@@ -1173,17 +1173,17 @@ class TestGitRename(unittest.TestCase):
     def test_renamed_file(self):
         # There was a file f.txt, then it was renamed to f2.txt.
         commits = list(self.repo.log(id_only=False, path='/f2.txt'))
-        self.assertEqual(len(commits), 4)
+        assert len(commits) == 4
         rename_commit = commits[1]
-        self.assertEqual(rename_commit['rename_details']['path'], '/f.txt')
-        self.assertEqual(
-            rename_commit['rename_details']['commit_url'],
+        assert rename_commit['rename_details']['path'] == '/f.txt'
+        assert \
+            rename_commit['rename_details']['commit_url'] == \
             '/p/test/src-git/ci/fbb0644603bb6ecee3ebb62efe8c86efc9b84ee6/'
-        )
-        self.assertEqual(rename_commit['size'], 19)
-        self.assertEqual(commits[2]['size'], 19)
+
+        assert rename_commit['size'] == 19
+        assert commits[2]['size'] == 19
 
     def test_merge_commit(self):
         merge_sha = '13951944969cf45a701bf90f83647b309815e6d5'
         commit = next(self.repo.log(revs=merge_sha, id_only=False))
-        self.assertEqual(commit['rename_details'], {})
+        assert commit['rename_details'] == {}
diff --git a/ForgeImporters/forgeimporters/github/tests/test_code.py b/ForgeImporters/forgeimporters/github/tests/test_code.py
index dbfca6430..247edcf44 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_code.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_code.py
@@ -94,17 +94,17 @@ class TestGitHubImportController(TestController, TestCase):
                 test_project_with_repo),
             params,
             status=302)
-        self.assertEqual(
-            r.location, 'http://localhost/p/{}/admin/'.format(
-                test_project_with_repo))
-        self.assertEqual(
-            'mymount', import_tool.post.call_args[1]['mount_point'])
-        self.assertEqual(
-            'mylabel', import_tool.post.call_args[1]['mount_label'])
-        self.assertEqual(
-            'poop', import_tool.post.call_args[1]['project_name'])
-        self.assertEqual('spooky', import_tool.post.call_args[1]['user_name'])
-        self.assertEqual(requests.head.call_count, 1)
+        assert \
+            r.location == 'http://localhost/p/{}/admin/'.format(
+                test_project_with_repo)
+        assert \
+            'mymount' == import_tool.post.call_args[1]['mount_point']
+        assert \
+            'mylabel' == import_tool.post.call_args[1]['mount_label']
+        assert \
+            'poop' == import_tool.post.call_args[1]['project_name']
+        assert 'spooky' == import_tool.post.call_args[1]['user_name']
+        assert requests.head.call_count == 1
 
     @with_git
     @patch('forgeimporters.github.requests')
@@ -125,12 +125,12 @@ class TestGitHubImportController(TestController, TestCase):
                 test_project_with_repo),
             params,
             status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
 
     @with_git
     @patch.object(GitHubOAuthMixin, 'oauth_begin')
     def test_oauth(self, oauth_begin):
         self.app.get(
             f'/p/{test_project_with_repo}/admin/ext/import/github-repo/')
-        self.assertEqual(oauth_begin.call_count, 1)
+        assert oauth_begin.call_count == 1
diff --git a/ForgeImporters/forgeimporters/github/tests/test_oauth.py b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
index d9be9ed5b..6d09017d8 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_oauth.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
@@ -49,10 +49,10 @@ class TestGitHubOAuthMixin(TestController, TestCase):
         req.post.return_value = Mock(status_code=404, json=Mock(return_value={}))
         assert not self.mix.oauth_has_access('write:repo_hook')
         call_args = req.post.call_args[0]
-        self.assertEqual(call_args, ('https://api.github.com/applications/123456/token',))
+        assert call_args == ('https://api.github.com/applications/123456/token',)
         call_kwargs = req.post.call_args[1]
         assert call_kwargs['auth']
-        self.assertEqual(call_kwargs['json'], {'access_token': 'some-token'})
+        assert call_kwargs['json'] == {'access_token': 'some-token'}
 
     @patch.dict(config, {'github_importer.client_id': '123456',
                          'github_importer.client_secret': 'deadbeef'})
@@ -78,5 +78,5 @@ class TestGitHubOAuthMixin(TestController, TestCase):
         with patch.object(self.mix, 'oauth_callback_complete') as _mock, \
                 patch('forgeimporters.github.redirect') as tg_redir:
             self.mix.handle_oauth_callback()
-        self.assertEqual(_mock.call_count, 1)
-        self.assertEqual(tg_redir.call_count, 1)
+        assert _mock.call_count == 1
+        assert tg_redir.call_count == 1
diff --git a/ForgeImporters/forgeimporters/github/tests/test_tracker.py b/ForgeImporters/forgeimporters/github/tests/test_tracker.py
index 6fdc63338..ffd19e392 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_tracker.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_tracker.py
@@ -55,16 +55,12 @@ class TestGitHubTrackerImportController(TestController, TestCase):
             mount_point='issues',
             mount_label='Issues')
         r = self.app.post(self.url + 'create', params, status=302)
-        self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
-                         test_project_with_tracker)
-        self.assertEqual(
-            'Issues', import_tool.post.call_args[1]['mount_label'])
-        self.assertEqual(
-            'issues', import_tool.post.call_args[1]['mount_point'])
-        self.assertEqual(
-            'mulder', import_tool.post.call_args[1]['project_name'])
-        self.assertEqual('spooky', import_tool.post.call_args[1]['user_name'])
-        self.assertEqual(requests.head.call_count, 1)
+        assert r.location == 'http://localhost/p/%s/admin/' % test_project_with_tracker
+        assert 'Issues' == import_tool.post.call_args[1]['mount_label']
+        assert 'issues' == import_tool.post.call_args[1]['mount_point']
+        assert 'mulder' == import_tool.post.call_args[1]['project_name']
+        assert 'spooky' == import_tool.post.call_args[1]['user_name']
+        assert requests.head.call_count == 1
 
     @with_tracker
     @patch('forgeimporters.github.requests')
@@ -80,11 +76,11 @@ class TestGitHubTrackerImportController(TestController, TestCase):
             mount_point='issues',
             mount_label='Issues')
         r = self.app.post(self.url + 'create', params, status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
 
     @with_tracker
     @patch.object(GitHubOAuthMixin, 'oauth_begin')
     def test_oauth(self, oauth_begin):
         self.app.get(self.url)
-        self.assertEqual(oauth_begin.call_count, 1)
+        assert oauth_begin.call_count == 1
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index 4a440ad07..61b22f5d4 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -572,15 +572,14 @@ class TestGitHubWikiImportController(TestController, TestCase):
             mount_label='GitHub Wiki',
             tool_option='import_history')
         r = self.app.post(self.url + 'create', params, status=302)
-        self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
-                         test_project_with_wiki)
+        assert r.location == 'http://localhost/p/%s/admin/' % test_project_with_wiki
         args = import_tool.post.call_args[1]
-        self.assertEqual('GitHub Wiki', args['mount_label'])
-        self.assertEqual('gh-wiki', args['mount_point'])
-        self.assertEqual('mulder', args['project_name'])
-        self.assertEqual('spooky', args['user_name'])
-        self.assertEqual('import_history', args['tool_option'])
-        self.assertEqual(requests.head.call_count, 1)
+        assert 'GitHub Wiki' == args['mount_label']
+        assert 'gh-wiki' == args['mount_point']
+        assert 'mulder' == args['project_name']
+        assert 'spooky' == args['user_name']
+        assert 'import_history' == args['tool_option']
+        assert requests.head.call_count == 1
 
     @with_wiki
     @patch('forgeimporters.github.requests')
@@ -594,15 +593,14 @@ class TestGitHubWikiImportController(TestController, TestCase):
             mount_label='GitHub Wiki'
         )
         r = self.app.post(self.url + 'create', params, status=302)
-        self.assertEqual(r.location, 'http://localhost/p/%s/admin/' %
-                         test_project_with_wiki)
+        assert r.location, 'http://localhost/p/%s/admin/' % test_project_with_wiki
         args = import_tool.post.call_args[1]
-        self.assertEqual('GitHub Wiki', args['mount_label'])
-        self.assertEqual('gh-wiki', args['mount_point'])
-        self.assertEqual('mulder', args['project_name'])
-        self.assertEqual('spooky', args['user_name'])
-        self.assertEqual('', args['tool_option'])
-        self.assertEqual(requests.head.call_count, 1)
+        assert 'GitHub Wiki' == args['mount_label']
+        assert 'gh-wiki' == args['mount_point']
+        assert 'mulder' == args['project_name']
+        assert 'spooky' == args['user_name']
+        assert '' == args['tool_option']
+        assert requests.head.call_count == 1
 
     @with_wiki
     @patch('forgeimporters.github.requests')
@@ -618,11 +616,11 @@ class TestGitHubWikiImportController(TestController, TestCase):
             mount_point='gh-wiki',
             mount_label='GitHub Wiki')
         r = self.app.post(self.url + 'create', params, status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
 
     @with_wiki
     @patch.object(GitHubOAuthMixin, 'oauth_begin')
     def test_oauth(self, oauth_begin):
         self.app.get(self.url)
-        self.assertEqual(oauth_begin.call_count, 1)
+        assert oauth_begin.call_count == 1
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_discussion.py b/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
index d135c6985..cb694c200 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
@@ -207,10 +207,10 @@ class TestDiscussionImporter(TestCase):
 
         importer.get_user.assert_called_once_with('admin1')
 
-        self.assertEqual(h.push_config.call_args_list, [
+        assert h.push_config.call_args_list == [
             mock.call(c, app=app),
             mock.call(c, user=admin, app=app)
-        ])
+        ]
 
         post = _json["forums"][0]["threads"][0]["posts"][0]
         thread1.add_post.assert_called_once_with(
@@ -399,7 +399,7 @@ class TestDiscussionImporter(TestCase):
             mock.call(dict(headers=dict(Subject=thread_json[4]["subject"])))
         ])
 
-        self.assertEqual(importer.add_posts.call_count, 5)
+        assert importer.add_posts.call_count == 5
         m.AuditLog.log.assert_called_once()
         g.post_event.assert_called_once()
 
@@ -449,7 +449,7 @@ class TestDiscussionImporter(TestCase):
 
         importer.import_tool(project, user, 'mount_point', 'mount_label')
 
-        self.assertEqual(import_id, forum.import_id)
+        assert import_id == forum.import_id
 
         # Test without import id
         _json = {
@@ -468,7 +468,7 @@ class TestDiscussionImporter(TestCase):
 
         importer.import_tool(project, user, 'mount_point', 'mount_label')
 
-        self.assertEqual('', forum.import_id)
+        assert '' == forum.import_id
 
     @mock.patch.object(discussion, 'c')
     @mock.patch.object(discussion, 'g')
@@ -521,7 +521,7 @@ class TestDiscussionImporter(TestCase):
 
         importer.import_tool(project, user, 'mount_point', 'mount_label')
 
-        self.assertEqual(import_id, thread.import_id)
+        assert import_id == thread.import_id
 
         # Test with no import id
         _json = {
@@ -545,7 +545,7 @@ class TestDiscussionImporter(TestCase):
 
         importer.import_tool(project, user, 'mount_point', 'mount_label')
 
-        self.assertEqual('', thread.import_id)
+        assert '' == thread.import_id
 
     @mock.patch.object(discussion, 'c')
     @mock.patch.object(discussion, 'g')
@@ -659,7 +659,7 @@ class TestDiscussionImporter(TestCase):
         importer._load_json = mock.Mock(return_value=_json)
         self.__check_missing(project, user, importer, h, g, utils)
 
-        self.assertEqual(h.make_app_admin_only.call_count, 6)
+        assert h.make_app_admin_only.call_count == 6
 
     @mock.patch.object(discussion, 'c')
     @mock.patch.object(discussion, 'h')
@@ -758,10 +758,10 @@ class TestDiscussionImporter(TestCase):
 
         importer.add_posts(thread, _json, app)
 
-        self.assertEqual(8, importer.get_user.call_count)
-        self.assertEqual(8, h.push_config.call_count)
-        self.assertEqual(8, thread.add_post.call_count)
-        self.assertEqual(8, post.add_multiple_attachments.call_count)
+        assert 8 == importer.get_user.call_count
+        assert 8 == h.push_config.call_count
+        assert 8 == thread.add_post.call_count
+        assert 8 == post.add_multiple_attachments.call_count
 
     @mock.patch.object(discussion, 'c')
     @mock.patch.object(discussion, 'h')
@@ -815,7 +815,7 @@ class TestDiscussionImporter(TestCase):
 
         importer.add_posts(thread, _json, app)
 
-        self.assertEqual(post.last_edit_date, parse(_json[0]['last_edited']))
+        assert post.last_edit_date == parse(_json[0]['last_edited'])
 
         # Test with none
         importer, app, thread, user, post = self.__init_add_posts_tests()
@@ -834,7 +834,7 @@ class TestDiscussionImporter(TestCase):
         post.last_edit_date = '-'
         importer.add_posts(thread, _json, app)
 
-        self.assertEqual(post.last_edit_date, '-')
+        assert post.last_edit_date == '-'
 
         # Test with no last edited
         importer, app, thread, user, post = self.__init_add_posts_tests()
@@ -852,7 +852,7 @@ class TestDiscussionImporter(TestCase):
         post.last_edit_date = '-'
         importer.add_posts(thread, _json, app)
 
-        self.assertEqual(post.last_edit_date, '-')
+        assert post.last_edit_date == '-'
 
         # Test with junk last edited
         importer, app, thread, user, post = self.__init_add_posts_tests()
@@ -912,11 +912,11 @@ class TestDiscussionImporter(TestCase):
         importer.add_posts(thread, _json, app)
 
         post.add_multiple_attachments.assert_called_once()
-        self.assertEqual(File.call_args_list, [
+        assert File.call_args_list == [
             mock.call('http://www.foo.com/attachment0'),
             mock.call('http://www.foo.com/attachment1'),
             mock.call('http://www.foo.com/attachment2'),
-        ])
+        ]
 
     @mock.patch.object(discussion, 'File')
     @mock.patch.object(discussion, 'c')
@@ -1157,7 +1157,7 @@ class TestDiscussionImporter(TestCase):
         user.is_anonymous.return_value = False
         username = "testUser123"
 
-        self.assertEqual(importer.annotate_text('foo', user, username), 'foo')
+        assert importer.annotate_text('foo', user, username) == 'foo'
 
     def test_annotate_text_with_not_existing_user(self):
         """ This test tests the annotate_text method with a not existing user """
@@ -1175,7 +1175,7 @@ class TestDiscussionImporter(TestCase):
         # Text that the method should return
         return_text = f'*Originally created by:* {username}\n\n{text}'
 
-        self.assertEqual(importer.annotate_text(text, user, username), return_text)
+        assert importer.annotate_text(text, user, username) == return_text
 
     def test_annotate_text_with_anonymous_user(self):
         """ This test tests the annotate_text method with an anonymous user """
@@ -1190,8 +1190,8 @@ class TestDiscussionImporter(TestCase):
 
         text = 'foo'
 
-        self.assertEqual(importer.annotate_text(text, user, usernames[0]), text)
-        self.assertEqual(importer.annotate_text(text, user, usernames[1]), text)
+        assert importer.annotate_text(text, user, usernames[0]) == text
+        assert importer.annotate_text(text, user, usernames[1]) == text
 
     def test_annotate_text_with_unicode(self):
         """ This method tests if annotate text can handle unicode characters """
@@ -1236,10 +1236,10 @@ class TestDiscussionImporter(TestCase):
         text = None
         username = None
 
-        self.assertEqual(importer.annotate_text(text, user, username), '')
+        assert importer.annotate_text(text, user, username) == ''
 
         text = 'foo'
-        self.assertEqual(importer.annotate_text(text, user, username), text)
+        assert importer.annotate_text(text, user, username) == text
 
     def __get_forum_dict(self, app, forum_json):
         new_forum = dict(
@@ -1292,13 +1292,13 @@ class TestForgeDiscussionController(TestController, TestCase):
             'mount_point': 'mymount',
         }
         r = self.app.post('/p/test/admin/ext/import/forge-discussion/create', params, status=302)
-        self.assertEqual(r.location, 'http://localhost/p/test/admin/')
+        assert r.location == 'http://localhost/p/test/admin/'
         siu.assert_called_once_with(project,
                                     'discussions.json',
                                     '{"key": "val"}'
                                     )
-        self.assertEqual('mymount', import_tool.post.call_args[1]['mount_point'])
-        self.assertEqual('mylabel', import_tool.post.call_args[1]['mount_label'])
+        assert 'mymount' == import_tool.post.call_args[1]['mount_point']
+        assert 'mylabel' == import_tool.post.call_args[1]['mount_label']
 
     @with_discussion
     @mock.patch('forgeimporters.forge.discussion.save_importer_upload')
@@ -1315,5 +1315,5 @@ class TestForgeDiscussionController(TestController, TestCase):
         r = self.app.post('/p/test/admin/ext/import/forge-discussion/create',
                           params,
                           status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
index 53e251f82..ad1df8b8d 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
@@ -137,13 +137,13 @@ class TestTrackerImporter(TestCase):
             },
             foo='bar',
         )
-        self.assertEqual(importer.annotate.call_args_list, [
+        assert importer.annotate.call_args_list == [
             mock.call('d1', author, 'at1', label=' owned'),
             mock.call('ad1', reporter, 'rb1', label=' created'),
             mock.call('d2', anonymous, 'at2', label=' owned'),
             mock.call('ad2', anonymous, 'rb2', label=' created'),
-        ])
-        self.assertEqual(TM.Ticket.call_args_list, [
+        ]
+        assert TM.Ticket.call_args_list == [
             mock.call(
                 app_config_id=app.config._id,
                 import_id={
@@ -184,44 +184,44 @@ class TestTrackerImporter(TestCase):
                 votes=2,
                 assigned_to_id=None,
             ),
-        ])
-        self.assertEqual(tickets[0].private, False)
-        self.assertEqual(tickets[1].private, True)
-        self.assertEqual(importer.process_comments.call_args_list, [
+        ]
+        assert tickets[0].private is False
+        assert tickets[1].private is True
+        assert importer.process_comments.call_args_list == [
             mock.call(tickets[0], 'comments1'),
             mock.call(tickets[1], 'comments2'),
-        ])
-        self.assertEqual(tlos.flush_all.call_args_list, [
+        ]
+        assert tlos.flush_all.call_args_list == [
             mock.call(),
             mock.call(),
-        ])
-        self.assertEqual(session.return_value.flush.call_args_list, [
+        ]
+        assert session.return_value.flush.call_args_list == [
             mock.call(tickets[0]),
             mock.call(tickets[1]),
-        ])
-        self.assertEqual(session.return_value.expunge.call_args_list, [
+        ]
+        assert session.return_value.expunge.call_args_list == [
             mock.call(tickets[0]),
             mock.call(tickets[1]),
-        ])
-        self.assertEqual(app.globals.custom_fields, 'fields')
+        ]
+        assert app.globals.custom_fields == 'fields'
         importer.process_bins.assert_called_once_with(app, 'bins')
-        self.assertEqual(app.globals.last_ticket_num, 100)
+        assert app.globals.last_ticket_num == 100
         M.AuditLog.log.assert_called_once_with(
             'import tool mount_point from exported Allura JSON',
             project=project, user=user, url='foo')
         g.post_event.assert_called_once_with('project_updated')
         app.globals.invalidate_bin_counts.assert_called_once_with()
-        self.assertEqual(File.call_args_list, [
+        assert File.call_args_list == [
             mock.call('u1'),
             mock.call('u2'),
             mock.call('u3'),
             mock.call('u4'),
-        ])
-        self.assertEqual(tickets[0].add_multiple_attachments.call_args_list, [
-            mock.call(['f1', 'f2'])])
-        self.assertEqual(tickets[1].add_multiple_attachments.call_args_list, [
+        ]
+        assert tickets[0].add_multiple_attachments.call_args_list == [
+            mock.call(['f1', 'f2'])]
+        assert tickets[1].add_multiple_attachments.call_args_list == [
             mock.call(['f3', 'f4']),
-        ])
+        ]
 
     @mock.patch.object(tracker, 'ThreadLocalODMSession')
     @mock.patch.object(tracker, 'M')
@@ -251,26 +251,25 @@ class TestTrackerImporter(TestCase):
         M.User.anonymous.return_value = 'anon'
 
         M.User.by_username.return_value = 'bar'
-        self.assertEqual(importer.get_user('foo'), 'bar')
-        self.assertEqual(M.User.anonymous.call_count, 0)
+        assert importer.get_user('foo') == 'bar'
+        assert M.User.anonymous.call_count == 0
 
-        self.assertEqual(importer.get_user(None), 'anon')
-        self.assertEqual(M.User.anonymous.call_count, 1)
+        assert importer.get_user(None), 'anon'
+        assert M.User.anonymous.call_count == 1
 
         M.User.by_username.return_value = None
-        self.assertEqual(importer.get_user('foo'), 'anon')
-        self.assertEqual(M.User.anonymous.call_count, 2)
+        assert importer.get_user('foo') == 'anon'
+        assert M.User.anonymous.call_count == 2
 
     def test_annotate(self):
         importer = tracker.ForgeTrackerImporter()
         user = mock.Mock(_id=1)
         user.is_anonymous.return_value = False
-        self.assertEqual(importer.annotate('foo', user, 'bar'), 'foo')
+        assert importer.annotate('foo', user, 'bar') == 'foo'
         user.is_anonymous.return_value = True
-        self.assertEqual(importer.annotate('foo', user, 'bar'),
-                         '*Originally by:* bar\n\nfoo')
-        self.assertEqual(importer.annotate('foo', user, 'nobody'), 'foo')
-        self.assertEqual(importer.annotate('foo', user, None), 'foo')
+        assert importer.annotate('foo', user, 'bar') == '*Originally by:* bar\n\nfoo'
+        assert importer.annotate('foo', user, 'nobody') == 'foo'
+        assert importer.annotate('foo', user, None) == 'foo'
 
     @mock.patch.object(tracker, 'File')
     @mock.patch.object(tracker, 'c')
@@ -300,28 +299,28 @@ class TestTrackerImporter(TestCase):
 
         importer.process_comments(ticket, comments)
 
-        self.assertEqual(importer.get_user.call_args_list,
-                         [mock.call('a1'), mock.call('a2')])
-        self.assertEqual(importer.annotate.call_args_list, [
+        assert importer.get_user.call_args_list == \
+                         [mock.call('a1'), mock.call('a2')]
+        assert importer.annotate.call_args_list == [
             mock.call('t1', author, 'a1'),
             mock.call('t2', author, 'a2'),
-        ])
-        self.assertEqual(add_post.call_args_list, [
+        ]
+        assert add_post.call_args_list == [
             mock.call(text='at1', ignore_security=True,
                       timestamp=datetime(2013, 9, 1)),
             mock.call(text='at2', ignore_security=True,
                       timestamp=datetime(2013, 9, 2)),
-        ])
-        self.assertEqual(File.call_args_list, [
+        ]
+        assert File.call_args_list == [
             mock.call('u1'),
             mock.call('u2'),
             mock.call('u3'),
             mock.call('u4'),
-        ])
-        self.assertEqual(ama.call_args_list, [
+        ]
+        assert ama.call_args_list == [
             mock.call(['f1', 'f2']),
             mock.call(['f3', 'f4']),
-        ])
+        ]
 
     @mock.patch.object(tracker, 'TM')
     def test_process_bins(self, TM):
@@ -330,10 +329,10 @@ class TestTrackerImporter(TestCase):
         importer = tracker.ForgeTrackerImporter()
         importer.process_bins(app, [{'_id': 1, 'b': 1}, {'b': 2}])
         TM.Bin.query.remove.assert_called_once_with({'app_config_id': 1})
-        self.assertEqual(TM.Bin.call_args_list, [
+        assert TM.Bin.call_args_list == [
             mock.call(app_config_id=1, b=1),
             mock.call(app_config_id=1, b=2),
-        ])
+        ]
 
 
 class TestForgeTrackerImportController(TestController, TestCase):
@@ -364,12 +363,10 @@ class TestForgeTrackerImportController(TestController, TestCase):
         }
         r = self.app.post('/p/test/admin/bugs/_importer/create', params,
                           status=302)
-        self.assertEqual(r.location, 'http://localhost/p/test/admin/')
+        assert r.location == 'http://localhost/p/test/admin/'
         sui.assert_called_once_with(project, 'tickets.json', '{"key": "val"}')
-        self.assertEqual(
-            'mymount', import_tool.post.call_args[1]['mount_point'])
-        self.assertEqual(
-            'mylabel', import_tool.post.call_args[1]['mount_label'])
+        assert 'mymount' == import_tool.post.call_args[1]['mount_point']
+        assert 'mylabel' == import_tool.post.call_args[1]['mount_label']
 
     @with_tracker
     @mock.patch('forgeimporters.forge.tracker.save_importer_upload')
@@ -385,5 +382,5 @@ class TestForgeTrackerImportController(TestController, TestCase):
         }
         r = self.app.post('/p/test/admin/bugs/_importer/create', params,
                           status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
index 17b9fb18f..cc36dc5d8 100644
--- a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -36,12 +36,12 @@ class TestGitHubImportController(TestController, TestCase):
     def test_login_overlay(self):
         r = self.app.get('/p/import_project/github/',
                          extra_environ=dict(username='*anonymous'))
-        self.assertIn('GitHub Project Importer', r)
-        self.assertIn('Login Required', r)
+        assert 'GitHub Project Importer' in r
+        assert 'Login Required' in r
 
         r = self.app.post('/p/import_project/github/process',
                           extra_environ=dict(username='*anonymous'), status=302)
-        self.assertIn('/auth/', r.location)
+        assert '/auth/' in r.location
 
 
 class TestGitHubOAuth(TestController):
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
index 9baa6bcbf..7c4c45332 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -15,8 +15,8 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+import pytest
 import json
-from unittest import TestCase
 from io import BytesIO
 import six.moves.urllib.parse
 import six.moves.urllib.request
@@ -26,8 +26,7 @@ from mock import patch, Mock
 
 from ... import github
 
-
-class TestGitHubProjectExtractor(TestCase):
+class TestGitHubProjectExtractor:
     PROJECT_INFO = {
         'description': 'project description',
         'homepage': 'http://example.com',
@@ -83,78 +82,74 @@ class TestGitHubProjectExtractor(TestCase):
         response.info = lambda: headers
         return response
 
-    def setup_method(self, method):
-        self.extractor = github.GitHubProjectExtractor('test_project')
-        self.extractor.urlopen = self.mocked_urlopen
+    @pytest.fixture
+    def extractor(self):  # Changed from setup_method to fixture
+        extractor = github.GitHubProjectExtractor('test_project')
+        extractor.urlopen = self.mocked_urlopen
+        return extractor
+
+    def test_get_next_page_url(self, extractor):
+        assert extractor.get_next_page_url(None) is None
+        assert extractor.get_next_page_url('') is None
 
-    def test_get_next_page_url(self):
-        self.assertIsNone(self.extractor.get_next_page_url(None))
-        self.assertIsNone(self.extractor.get_next_page_url(''))
         link = '<https://api.github.com/repositories/8560576/issues?state=open&page=2>; rel="next", <https://api.github.com/repositories/8560576/issues?state=open&page=10>; rel="last"'
-        self.assertEqual(self.extractor.get_next_page_url(link),
-                         'https://api.github.com/repositories/8560576/issues?state=open&page=2')
+        assert extractor.get_next_page_url(link) == 'https://api.github.com/repositories/8560576/issues?state=open&page=2'
 
         link = '<https://api.github.com/repositories/8560576/issues?state=open&page=2>; rel="next"'
-        self.assertEqual(self.extractor.get_next_page_url(link),
-                         'https://api.github.com/repositories/8560576/issues?state=open&page=2')
+        assert extractor.get_next_page_url(link) == 'https://api.github.com/repositories/8560576/issues?state=open&page=2'
 
         link = '<https://api.github.com/repositories/8560576/issues?state=open&page=1>; rel="prev"'
-        self.assertIsNone(self.extractor.get_next_page_url(link))
+        assert extractor.get_next_page_url(link) is None
 
-    def test_get_summary(self):
-        self.assertEqual(self.extractor.get_summary(), 'project description')
+    def test_get_summary(self, extractor):
+        assert extractor.get_summary() == 'project description'
 
-    def test_get_homepage(self):
-        self.assertEqual(self.extractor.get_homepage(), 'http://example.com')
+    def test_get_homepage(self, extractor):
+        assert extractor.get_homepage() == 'http://example.com'
 
-    def test_iter_issues(self):
-        issues = list(self.extractor.iter_issues())
+    def test_iter_issues(self, extractor):
+        issues = list(extractor.iter_issues())
         all_issues = list(zip((1, 2), self.CLOSED_ISSUES_LIST))
         all_issues += list(zip((3, 4, 5), self.OPENED_ISSUES_LIST))
         all_issues += list(zip((6, 7, 8), self.OPENED_ISSUES_LIST_PAGE2))
-        self.assertEqual(issues, all_issues)
+        assert issues == all_issues
 
-    def test_iter_comments(self):
+    def test_iter_comments(self, extractor):
         mock_issue = {'comments_url': '/issues/1/comments'}
-        comments = list(self.extractor.iter_comments(mock_issue))
-        self.assertEqual(comments, self.ISSUE_COMMENTS +
-                         self.ISSUE_COMMENTS_PAGE2)
+        comments = list(extractor.iter_comments(mock_issue))
+        assert comments == self.ISSUE_COMMENTS + self.ISSUE_COMMENTS_PAGE2
 
-    def test_iter_events(self):
+    def test_iter_events(self, extractor):
         mock_issue = {'events_url': '/issues/1/events'}
-        events = list(self.extractor.iter_events(mock_issue))
-        self.assertEqual(events, self.ISSUE_EVENTS +
-                         self.ISSUE_EVENTS_PAGE2[:1])
+        events = list(extractor.iter_events(mock_issue))
+        assert events == self.ISSUE_EVENTS + self.ISSUE_EVENTS_PAGE2[:1]
 
-    def test_has_wiki(self):
-        assert self.extractor.has_wiki()
+    def test_has_wiki(self, extractor):
+        assert extractor.has_wiki()
 
-    def test_get_wiki_url(self):
-        self.assertEqual(self.extractor.get_page_url('wiki_url'),
-                         'https://github.com/test_project.wiki')
+    def test_get_wiki_url(self, extractor):
+        assert extractor.get_page_url('wiki_url') == 'https://github.com/test_project.wiki'
 
     @patch('forgeimporters.base.h.urlopen')
-    def test_urlopen(self, urlopen):
-        e = github.GitHubProjectExtractor('test_project')
+    def test_urlopen(self, urlopen, extractor):
         url = 'https://github.com/u/p/'
-        e.urlopen(url)
+        extractor.urlopen(url)
         request = urlopen.call_args[0][0]
-        self.assertEqual(request.get_full_url(), url)
+        assert request.get_full_url() == url
 
         user = Mock()
         user.get_tool_data.return_value = 'abc'
         e = github.GitHubProjectExtractor('test_project', user=user)
         e.urlopen(url)
         request = urlopen.call_args[0][0]
-        self.assertEqual(request.get_full_url(), url)
+        assert request.get_full_url() == url
         assert request.headers['User-agent']
-        self.assertEqual(request.headers['Authorization'], 'Bearer abc')
+        assert request.headers['Authorization'] == 'Bearer abc'
 
     @patch('forgeimporters.base.h.urlopen')
     @patch('forgeimporters.github.time.sleep')
     @patch('forgeimporters.github.log')
-    def test_urlopen_rate_limit_403(self, log, sleep, urlopen):
-        '''Test that urlopen catches 403 which may happen if limit exceeded by previous fetches'''
+    def test_urlopen_rate_limit_403(self, log, sleep, urlopen, extractor):
         limit_exceeded_headers = {
             'X-RateLimit-Limit': '10',
             'X-RateLimit-Remaining': '0',
@@ -168,10 +163,9 @@ class TestGitHubProjectExtractor(TestCase):
             raise six.moves.urllib.error.HTTPError(
                 'url', 403, 'msg', limit_exceeded_headers, BytesIO(b'{}'))
         urlopen.side_effect = urlopen_side_effect
-        e = github.GitHubProjectExtractor('test_project')
-        e.get_page('http://example.com/')
-        self.assertEqual(sleep.call_count, 1)
-        self.assertEqual(urlopen.call_count, 2)
+        extractor.get_page('http://example.com/')
+        assert sleep.call_count == 1
+        assert urlopen.call_count == 2
         log.warning.assert_called_once_with(
             'Rate limit exceeded (10 requests/hour). '
             'Sleeping until 2013-10-25 09:32:02 UTC'
@@ -182,4 +176,4 @@ class TestGitHubProjectExtractor(TestCase):
         head.return_value.status_code = 200
         assert github.GitHubProjectExtractor('my-project').check_readable()
         head.return_value.status_code = 404
-        assert not github.GitHubProjectExtractor('my-project').check_readable()
+        assert not github.GitHubProjectExtractor('my-project').check_readable()
\ No newline at end of file
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tracker.py b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
index faf378381..0224925ec 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
@@ -66,10 +66,10 @@ class TestTrackerImporter(TestCase):
                 'project_name': 'me/project_name',
             }
         )
-        self.assertEqual(tlos.flush_all.call_args_list, [
+        assert tlos.flush_all.call_args_list == [
             mock.call(),
             mock.call(),
-        ])
+        ]
         M.AuditLog.log.assert_called_once_with(
             'import tool mount_point from me/project_name on GitHub',
             project=project, user=user, url='foo')
@@ -96,17 +96,17 @@ class TestTrackerImporter(TestCase):
         with mock.patch.object(tracker, 'datetime') as dt:
             dt.strptime.side_effect = lambda s, f: s
             importer.process_fields(extractor, ticket, issue)
-            self.assertEqual(ticket.summary, 'title')
-            self.assertEqual(ticket.description,
-                             '*Originally created by:* [creator](https://github.com/creator)\n*Originally owned by:* [owner](https://github.com/owner)\n\nhello')
-            self.assertEqual(ticket.status, 'New')
-            self.assertEqual(ticket.created_date, 'created_at')
-            self.assertEqual(ticket.mod_date, 'updated_at')
-            self.assertEqual(dt.strptime.call_args_list, [
+            assert ticket.summary == 'title'
+            assert ticket.description == \
+                             '*Originally created by:* [creator](https://github.com/creator)\n*Originally owned by:* [owner](https://github.com/owner)\n\nhello'
+            assert ticket.status == 'New'
+            assert ticket.created_date == 'created_at'
+            assert ticket.mod_date == 'updated_at'
+            assert dt.strptime.call_args_list == [
                 mock.call('created_at', '%Y-%m-%dT%H:%M:%SZ'),
                 mock.call('updated_at', '%Y-%m-%dT%H:%M:%SZ'),
-            ])
-            self.assertEqual(ticket.labels, ['first', 'second'])
+            ]
+            assert ticket.labels == ['first', 'second']
 
     @mock.patch.object(tracker, 'c')
     def test_postprocess_milestones(self, c):
@@ -118,7 +118,7 @@ class TestTrackerImporter(TestCase):
         milestones = importer.postprocess_milestones()
         # for stable order
         milestones[0]['milestones'] = sorted(milestones[0]['milestones'], key=itemgetter('name'))
-        self.assertEqual(milestones, [
+        assert milestones == [
             {
                 'name': '_milestone',
                 'type': 'milestone',
@@ -130,7 +130,7 @@ class TestTrackerImporter(TestCase):
                             '2015-04-25', 'complete': False},
                 ],
             },
-        ])
+        ]
 
     def test_get_attachments(self):
         importer = tracker.GitHubTrackerImporter()
@@ -140,14 +140,14 @@ class TestTrackerImporter(TestCase):
             '![cdbpzjc5ex4](https://f.cloud.github.com/assets/979771/1027411/a393ab5e-0e70-11e3-8a38-b93a3df904cf.jpg)\r\n' \
             '![screensh0t](http://f.cl.ly/items/13453x43053r2G0d3x0v/Screen%20Shot%202012-04-28%20at%2010.48.17%20AM.png)'
         new_body, attachments = importer._get_attachments(extractor, body)
-        self.assertEqual(new_body, 'hello\n')
-        self.assertEqual(len(attachments), 2)
-        self.assertEqual(
-            attachments[0].url, 'https://f.cloud.github.com/assets/979771/1027411/a393ab5e-0e70-11e3-8a38-b93a3df904cf.jpg')
-        self.assertEqual(
-            attachments[1].url, 'http://f.cl.ly/items/13453x43053r2G0d3x0v/Screen%20Shot%202012-04-28%20at%2010.48.17%20AM.png')
-        self.assertEqual(attachments[0].file.read(), b'data')
-        self.assertEqual(attachments[1].file.read(), b'data')
+        assert new_body == 'hello\n'
+        assert len(attachments) == 2
+        assert \
+            attachments[0].url == 'https://f.cloud.github.com/assets/979771/1027411/a393ab5e-0e70-11e3-8a38-b93a3df904cf.jpg'
+        assert \
+            attachments[1].url == 'http://f.cl.ly/items/13453x43053r2G0d3x0v/Screen%20Shot%202012-04-28%20at%2010.48.17%20AM.png'
+        assert attachments[0].file.read() == b'data'
+        assert attachments[1].file.read() == b'data'
 
     def test_get_attachments_404(self):
         importer = tracker.GitHubTrackerImporter()
@@ -175,11 +175,11 @@ class TestTrackerImporter(TestCase):
         importer.github_markdown_converter = GitHubMarkdownConverter(
             'user', 'project')
         importer.process_comments(extractor, ticket, issue)
-        self.assertEqual(ticket.discussion_thread.add_post.call_args_list[0], mock.call(
+        assert ticket.discussion_thread.add_post.call_args_list[0] == mock.call(
             text='*Originally posted by:* [me](https://github.com/me)\n\nhello',
             timestamp=datetime(2013, 8, 26, 16, 57, 53),
             ignore_security=True,
-        ))
+        )
 
     def test_process_events(self):
         ticket = mock.Mock()
@@ -210,24 +210,24 @@ class TestTrackerImporter(TestCase):
         importer = tracker.GitHubTrackerImporter()
         importer.process_events(extractor, ticket, issue)
         args = ticket.discussion_thread.add_post.call_args_list
-        self.assertEqual(args[0], mock.call(
+        assert args[0] == mock.call(
             text='*Ticket changed by:* [darth](https://github.com/darth)\n\n'
                  '- **status**: open --> closed',
             timestamp=datetime(2013, 9, 12, 9, 58, 49),
-            ignore_security=True))
-        self.assertEqual(args[1], mock.call(
+            ignore_security=True)
+        assert args[1] == mock.call(
             text='*Ticket changed by:* [yoda](https://github.com/yoda)\n\n'
                  '- **status**: closed --> open',
             timestamp=datetime(2013, 9, 12, 10, 13, 20),
-            ignore_security=True))
-        self.assertEqual(args[2], mock.call(
+            ignore_security=True)
+        assert args[2] == mock.call(
             text='- **assigned_to**: [luke](https://github.com/luke)',
             timestamp=datetime(2013, 9, 12, 10, 14, 0),
-            ignore_security=True))
-        self.assertEqual(args[3], mock.call(
+            ignore_security=True)
+        assert args[3] == mock.call(
             text='- **assigned_to**: [ghost](https://github.com/ghost)',
             timestamp=datetime(2013, 9, 12, 10, 14, 0),
-            ignore_security=True))
+            ignore_security=True)
 
     def test_github_markdown_converted_in_description(self):
         ticket = mock.Mock()
@@ -264,7 +264,7 @@ Hello
         with mock.patch.object(tracker, 'datetime') as dt:
             dt.strptime.side_effect = lambda s, f: s
             importer.process_fields(extractor, ticket, issue)
-        self.assertEqual(ticket.description.strip(), body_converted.strip())
+        assert ticket.description.strip() == body_converted.strip()
 
     def test_github_markdown_converted_in_comments(self):
         ticket = mock.Mock()
@@ -295,8 +295,8 @@ Hello
         importer.github_markdown_converter = GitHubMarkdownConverter(
             'user', 'project')
         importer.process_comments(extractor, ticket, issue)
-        self.assertEqual(ticket.discussion_thread.add_post.call_args_list[0], mock.call(
+        assert ticket.discussion_thread.add_post.call_args_list[0] == mock.call(
             text=body_converted,
             timestamp=datetime(2013, 8, 26, 16, 57, 53),
             ignore_security=True,
-        ))
+        )
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index dc8e5b1aa..f97efa390 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -43,7 +43,7 @@ class TestProjectExtractor(TestCase):
         req.add_header.assert_called_once_with(
             'User-Agent', 'Allura Data Importer (https://allura.apache.org/)')
         urlopen.assert_called_once_with(req, retries=3, codes=(408, 500, 502, 503, 504), timeout=120)
-        self.assertEqual(r, urlopen.return_value)
+        assert r == urlopen.return_value
 
     def test_urlopen_invalid(self):
         with pytest.raises(ValueError):
@@ -150,8 +150,8 @@ class TestProjectImporter(TestCase):
             ep('ep1', 'foo'), ep('ep2', 'bar'), ep('ep3', 'foo')]
         pi = base.ProjectImporter(mock.Mock(name='neighborhood'))
         pi.source = 'foo'
-        self.assertEqual(pi.tool_importers,
-                         {'ep1': eps[0].lv, 'ep3': eps[2].lv})
+        assert pi.tool_importers == \
+                         {'ep1': eps[0].lv, 'ep3': eps[2].lv}
         iep.assert_called_once_with('allura.importers')
 
     @mock.patch.object(base.ToolImporter, 'by_name')
@@ -181,7 +181,7 @@ class TestProjectImporter(TestCase):
         import_tool.post.assert_called_once_with(
             'forgeimporters.base.ToolImporter', **kw)
         M.AuditLog.log.assert_called_once_with('import project from Source')
-        self.assertEqual(flash.call_count, 1)
+        assert flash.call_count == 1
         redirect.assert_called_once_with('script_name/admin/overview')
 
     @mock.patch.object(base.h, 'request')
@@ -194,18 +194,18 @@ class TestProjectImporter(TestCase):
         c.show_login_overlay = False
         request.path = '/test-importer/'
         pi._check_security()
-        self.assertEqual(c.show_login_overlay, True)
+        assert c.show_login_overlay is True
 
         c.show_login_overlay = False
         request.path = '/test-importer/check_names/'
         pi._check_security()
-        self.assertEqual(c.show_login_overlay, True)
+        assert c.show_login_overlay is True
 
         c.show_login_overlay = False
         request.path = '/test-importer/process/'
         with td.raises(HTTPUnauthorized):
             pi._check_security()
-        self.assertEqual(c.show_login_overlay, False)
+        assert c.show_login_overlay is False
 
 
 TA1 = mock.Mock(tool_label='foo', tool_description='foo_desc')
@@ -241,13 +241,13 @@ class TestToolImporter(TestCase):
         eps = iep.return_value = [ep('my-name', 'my-source')]
         importer = base.ToolImporter.by_name('my-name')
         iep.assert_called_once_with('allura.importers', 'my-name')
-        self.assertEqual(importer, eps[0].lv)
+        assert importer == eps[0].lv
 
         iep.reset_mock()
         iep.return_value = []
         importer = base.ToolImporter.by_name('other-name')
         iep.assert_called_once_with('allura.importers', 'other-name')
-        self.assertEqual(importer, None)
+        assert importer is None
 
     @mock.patch.object(base.h, 'iter_entry_points')
     def test_by_app(self, iep):
@@ -257,22 +257,22 @@ class TestToolImporter(TestCase):
             ep('importer3', importer=TI3),
         ]
         importers = base.ToolImporter.by_app(TA2)
-        self.assertEqual(set(importers.keys()), {
+        assert set(importers.keys()) == {
             'importer2',
             'importer3',
-        })
+        }
         self.assertIsInstance(importers['importer2'], TI2)
         self.assertIsInstance(importers['importer3'], TI3)
 
     def test_tool_label(self):
-        self.assertEqual(TI1().tool_label, 'foo')
-        self.assertEqual(TI2().tool_label, 'bar')
-        self.assertEqual(TI3().tool_label, 'qux')
+        assert TI1().tool_label == 'foo'
+        assert TI2().tool_label == 'bar'
+        assert TI3().tool_label == 'qux'
 
     def test_tool_description(self):
-        self.assertEqual(TI1().tool_description, 'foo_desc')
-        self.assertEqual(TI2().tool_description, 'bar_desc')
-        self.assertEqual(TI3().tool_description, 'qux_desc')
+        assert TI1().tool_description == 'foo_desc'
+        assert TI2().tool_description == 'bar_desc'
+        assert TI3().tool_description == 'qux_desc'
 
 
 class TestToolsValidator(TestCase):
@@ -282,15 +282,15 @@ class TestToolsValidator(TestCase):
 
     @mock.patch.object(base.ToolImporter, 'by_name')
     def test_empty(self, by_name):
-        self.assertEqual(self.tv.to_python(''), [])
-        self.assertEqual(by_name.call_count, 0)
+        assert self.tv.to_python('') == []
+        assert by_name.call_count == 0
 
     @mock.patch.object(base.ToolImporter, 'by_name')
     def test_no_ep(self, by_name):
         eps = by_name.return_value = None
         with self.assertRaises(Invalid) as cm:
             self.tv.to_python('my-value')
-        self.assertEqual(cm.exception.msg, 'Invalid tool selected: my-value')
+        assert cm.exception.msg == 'Invalid tool selected: my-value'
         by_name.assert_called_once_with('my-value')
 
     @mock.patch.object(base.ToolImporter, 'by_name')
@@ -298,7 +298,7 @@ class TestToolsValidator(TestCase):
         eps = by_name.return_value = ep('ep1', 'bad-source').lv
         with self.assertRaises(Invalid) as cm:
             self.tv.to_python('my-value')
-        self.assertEqual(cm.exception.msg, 'Invalid tool selected: my-value')
+        assert cm.exception.msg == 'Invalid tool selected: my-value'
         by_name.assert_called_once_with('my-value')
 
     @mock.patch.object(base.ToolImporter, 'by_name')
@@ -307,24 +307,24 @@ class TestToolsValidator(TestCase):
             ep('ep1', 'bad-source').lv, ep('ep2', 'good-source').lv, ep('ep3', 'bad-source').lv]
         with self.assertRaises(Invalid) as cm:
             self.tv.to_python(['value1', 'value2', 'value3'])
-        self.assertEqual(cm.exception.msg,
-                         'Invalid tools selected: value1, value3')
-        self.assertEqual(by_name.call_args_list, [
+        assert cm.exception.msg == \
+                         'Invalid tools selected: value1, value3'
+        assert by_name.call_args_list == [
             mock.call('value1'),
             mock.call('value2'),
             mock.call('value3'),
-        ])
+        ]
 
     @mock.patch.object(base.ToolImporter, 'by_name')
     def test_valid(self, by_name):
         eps = by_name.side_effect = [
             ep('ep1', 'good-source').lv, ep('ep2', 'good-source').lv, ep('ep3', 'bad-source').lv]
-        self.assertEqual(
-            self.tv.to_python(['value1', 'value2']), ['value1', 'value2'])
-        self.assertEqual(by_name.call_args_list, [
+        assert \
+            self.tv.to_python(['value1', 'value2']) == ['value1', 'value2']
+        assert by_name.call_args_list == [
             mock.call('value1'),
             mock.call('value2'),
-        ])
+        ]
 
 
 class TestProjectToolsImportController(TestController):
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 9336faf30..e95f586ac 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -67,7 +67,7 @@ class TestTracTicketImporter(TestCase):
                                    trac_url='http://example.com/trac/url',
                                    user_map=json.dumps(user_map),
                                    )
-        self.assertEqual(res, app)
+        assert res == app
         project.install_app.assert_called_once_with(
             'Tickets', mount_point='bugs', mount_label='Bugs',
             open_status_names='new assigned accepted reopened',
@@ -136,15 +136,15 @@ class TestTracTicketImportController(TestController, TestCase):
                               'user_map', 'myfile', b'{"orig_user": "new_user"}'
                           )],
                           status=302)
-        self.assertEqual(r.location, 'http://localhost/p/test/admin/')
-        self.assertEqual(
-            'mymount', import_tool.post.call_args[1]['mount_point'])
-        self.assertEqual(
-            'mylabel', import_tool.post.call_args[1]['mount_label'])
-        self.assertEqual('{"orig_user": "new_user"}',
-                         import_tool.post.call_args[1]['user_map'])
-        self.assertEqual('http://example.com/trac/url/',
-                         import_tool.post.call_args[1]['trac_url'])
+        assert r.location == 'http://localhost/p/test/admin/'
+        assert \
+            'mymount' == import_tool.post.call_args[1]['mount_point']
+        assert \
+            'mylabel' == import_tool.post.call_args[1]['mount_label']
+        assert '{"orig_user": "new_user"}' == \
+                         import_tool.post.call_args[1]['user_map']
+        assert 'http://example.com/trac/url/' == \
+                         import_tool.post.call_args[1]['trac_url']
 
     @with_tracker
     @patch('forgeimporters.trac.requests.head')
@@ -163,8 +163,8 @@ class TestTracTicketImportController(TestController, TestCase):
                               'user_map', 'myfile', b'{"orig_user": "new_user"}'
                           )],
                           status=302).follow()
-        self.assertIn('Please wait and try again', r)
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert 'Please wait and try again' in r
+        assert import_tool.post.call_count == 0
 
     @with_tracker
     @patch('forgeimporters.trac.requests.head')
@@ -179,7 +179,7 @@ class TestTracTicketImportController(TestController, TestCase):
                           upload_files=[(
                               'user_map', 'myfile', b'{"orig_user": "new_user"}'
                           )])
-        self.assertEqual(import_tool.post.call_count, 0)
+        assert import_tool.post.call_count == 0
 
     @with_tracker
     @patch('forgeimporters.trac.requests.head')
@@ -190,7 +190,7 @@ class TestTracTicketImportController(TestController, TestCase):
                       mount_label='mylabel',
                       mount_point='mymount')
         r = self.app.post('/p/test/admin/ext/import/trac-tickets/create', params, status=200)
-        self.assertIn('Invalid URL', r.text)
+        assert 'Invalid URL' in r.text
 
 class TestTracImportSupport(TestCase):
 
@@ -221,7 +221,7 @@ class TestTracImportSupport(TestCase):
         }
         for input, expected in cases.items():
             actual = import_support.link_processing(input)
-            self.assertEqual(actual, expected)
+            assert actual == expected
 
 
 class TestTracImportSupportFunctional(TestRestApiBase, TestCase):
@@ -262,10 +262,10 @@ class TestTracImportSupportFunctional(TestRestApiBase, TestCase):
             status={'$in': ['ok', 'pending']})).sort('timestamp').all()
 
         import_support = TracImportSupport()
-        self.assertEqual(
-            import_support.get_slug_by_id('204', '1'), comments[0].slug)
-        self.assertEqual(
-            import_support.get_slug_by_id('204', '2'), comments[1].slug)
+        assert \
+            import_support.get_slug_by_id('204', '1') == comments[0].slug
+        assert \
+            import_support.get_slug_by_id('204', '2') == comments[1].slug
 
     @with_tracker
     @skipIf(module_not_available('html2text'), 'html2text required')
@@ -287,8 +287,8 @@ class TestTracImportSupportFunctional(TestRestApiBase, TestCase):
             '{"user_map": {}}')
         ticket = TM.Ticket.query.get(app_config_id=c.app.config._id,
                                      ticket_num=390)
-        self.assertIn('To reproduce:  \n\\- open an mzML file',
-                      ticket.description)
-        self.assertIn('duplicate of:  \n\\- [#316](316 "defect: SpectraViewWidget is',
-                      ticket.discussion_thread.find_posts()[0].text)
-        self.assertIn('will crash TOPPView.', ticket.description)
+        assert 'To reproduce:  \n\\- open an mzML file' in \
+                      ticket.description
+        assert 'duplicate of:  \n\\- [#316](316 "defect: SpectraViewWidget is' in \
+                      ticket.discussion_thread.find_posts()[0].text
+        assert 'will crash TOPPView.' in ticket.description
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 9ab8de8e8..7c7affae7 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -167,10 +167,9 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
             os.path.join(g.tmpdir, 'testsvn/hooks/post-commit'), os.X_OK)
         with open(os.path.join(g.tmpdir, 'testsvn/hooks/post-commit')) as f:
             hook_data = f.read()
-        self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src/\n',
-            hook_data)
-        self.assertIn('exec $DIR/post-commit-user "$@"\n', hook_data)
+        assert \
+            'curl -s http://localhost/auth/refresh_repo/p/test/src/\n' in hook_data
+        assert 'exec $DIR/post-commit-user "$@"\n' in hook_data
 
         repo.refresh(notify=False)
         assert len(list(repo.log(limit=100)))
@@ -219,9 +218,8 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
             os.path.join(g.tmpdir, 'testsvn/hooks/post-commit'), os.X_OK)
         with open(os.path.join(g.tmpdir, 'testsvn/hooks/post-commit')) as f:
             c = f.read()
-        self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src/\n', c)
-        self.assertIn('exec $DIR/post-commit-user "$@"\n', c)
+        assert  'curl -s http://localhost/auth/refresh_repo/p/test/src/\n' in c
+        assert 'exec $DIR/post-commit-user "$@"\n' in c
 
         repo.refresh(notify=False)
         assert len(list(repo.log(limit=100)))
@@ -359,50 +357,50 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
     def test_paged_diffs(self):
         entry = self.repo.commit(next(self.repo.log(2, id_only=True, limit=1)))
-        self.assertEqual(entry.diffs, entry.paged_diffs())
-        self.assertEqual(entry.diffs, entry.paged_diffs(start=0))
+        assert entry.diffs == entry.paged_diffs()
+        assert entry.diffs == entry.paged_diffs(start=0)
         added_expected = entry.diffs.added[1:3]
         expected = dict(
             copied=[], changed=[], removed=[], renamed=[],
             added=added_expected, total=4)
         actual = entry.paged_diffs(start=1, end=3)
-        self.assertEqual(expected, actual)
+        assert expected == actual
 
         fake_id = self.repo._impl._oid(100)
         empty = M.repository.Commit(_id=fake_id, repo=self.repo).paged_diffs()
-        self.assertEqual(sorted(actual.keys()), sorted(empty.keys()))
+        assert sorted(actual.keys()) == sorted(empty.keys())
 
     def test_diff_create_file(self):
         entry = self.repo.commit(next(self.repo.log(1, id_only=True, limit=1)))
-        self.assertEqual(
-            entry.diffs, dict(
+        assert \
+            entry.diffs == dict(
                 copied=[], changed=[], renamed=[],
-                removed=[], added=['/README'], total=1))
+                removed=[], added=['/README'], total=1)
 
     def test_diff_create_path(self):
         entry = self.repo.commit(next(self.repo.log(2, id_only=True, limit=1)))
         actual = entry.diffs
         actual.added = sorted(actual.added)
-        self.assertEqual(
-            entry.diffs, dict(
+        assert \
+            entry.diffs == dict(
                 copied=[], changed=[], removed=[], renamed=[],
                 added=sorted([
                     '/a', '/a/b', '/a/b/c',
-                    '/a/b/c/hello.txt']), total=4))
+                    '/a/b/c/hello.txt']), total=4)
 
     def test_diff_modify_file(self):
         entry = self.repo.commit(next(self.repo.log(3, id_only=True, limit=1)))
-        self.assertEqual(
-            entry.diffs, dict(
+        assert \
+            entry.diffs == dict(
                 copied=[], changed=['/README'], renamed=[],
-                removed=[], added=[], total=1))
+                removed=[], added=[], total=1)
 
     def test_diff_delete(self):
         entry = self.repo.commit(next(self.repo.log(4, id_only=True, limit=1)))
-        self.assertEqual(
-            entry.diffs, dict(
+        assert \
+            entry.diffs == dict(
                 copied=[], changed=[], renamed=[],
-                removed=['/a/b/c/hello.txt'], added=[], total=1))
+                removed=['/a/b/c/hello.txt'], added=[], total=1)
 
     def test_diff_copy(self):
         entry = self.repo.commit(next(self.repo.log(5, id_only=True, limit=1)))
@@ -741,14 +739,13 @@ class TestRepo(_TestWithRepo):
             getattr(self.repo._impl, fn).assert_called_with('foo')
 
     def test_shorthand_for_commit(self):
-        self.assertEqual(
-            self.repo.shorthand_for_commit('a' * 40),
-            '[aaaaaa]')
+        assert \
+            self.repo.shorthand_for_commit('a' * 40) == '[aaaaaa]'
 
     def test_url_for_commit(self):
-        self.assertEqual(
-            self.repo.url_for_commit('a' * 40),
-            '/p/test/test1/ci/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/')
+        assert \
+            self.repo.url_for_commit('a' * 40) == \
+            '/p/test/test1/ci/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/'
 
     @mock.patch('allura.model.repository.g.post_event')
     def test_init_as_clone(self, post_event):
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index d0af09fcc..dfc72a012 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -113,19 +113,19 @@ def create_ticket(summary, custom_fields):
 class test_change_text(unittest.TestCase):
 
     def test_get_label(self):
-        self.assertEqual('Milestone', tracker_main.get_label('_milestone'))
-        self.assertEqual('Ticket Number', tracker_main.get_label('ticket_num'))
-        self.assertEqual('Summary', tracker_main.get_label('summary'))
-        self.assertEqual('Status', tracker_main.get_label('status'))
-        self.assertEqual('Owner', tracker_main.get_label('assigned_to'))
-        self.assertEqual(None, tracker_main.get_label('test'))
+        assert 'Milestone' == tracker_main.get_label('_milestone')
+        assert 'Ticket Number' == tracker_main.get_label('ticket_num')
+        assert 'Summary' == tracker_main.get_label('summary')
+        assert 'Status' == tracker_main.get_label('status')
+        assert 'Owner' == tracker_main.get_label('assigned_to')
+        assert None is tracker_main.get_label('test')
 
     def test_get_change_text(self):
-        self.assertEqual(
-            '- **test**: value2 --> value1\n',
-            tracker_main.get_change_text('test', 'value1', 'value2'))
+        assert \
+            '- **test**: value2 --> value1\n' == \
+            tracker_main.get_change_text('test', 'value1', 'value2')
 
     def test_get_change_text_for_lists(self):
-        self.assertEqual(
-            '- **test**: v1, v2 --> v3, v4, v5\n',
-            tracker_main.get_change_text('test', ['v3', 'v4', 'v5'], ['v1', 'v2']))
+        assert \
+            '- **test**: v1, v2 --> v3, v4, v5\n' == \
+            tracker_main.get_change_text('test', ['v3', 'v4', 'v5'], ['v1', 'v2'])
diff --git a/ForgeUserStats/forgeuserstats/tests/test_model.py b/ForgeUserStats/forgeuserstats/tests/test_model.py
index 1a7720a11..f6a6d7078 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -442,11 +442,11 @@ class TestUserStats(unittest.TestCase):
 
     def test_start_date(self):
         stats = USM.UserStats(registration_date=datetime(2012, 4, 1))
-        self.assertEqual(stats.start_date, datetime(2012, 4, 1))
+        assert stats.start_date == datetime(2012, 4, 1)
         with h.push_config(config, **{'userstats.start_date': '2013-04-01'}):
-            self.assertEqual(stats.start_date, datetime(2013, 4, 1))
+            assert stats.start_date == datetime(2013, 4, 1)
         with h.push_config(config, **{'userstats.start_date': '2011-04-01'}):
-            self.assertEqual(stats.start_date, datetime(2012, 4, 1))
+            assert stats.start_date == datetime(2012, 4, 1)
 
     @mock.patch('allura.model.stats.difflib.unified_diff')
     def test_count_loc(self, unified_diff):
@@ -472,11 +472,11 @@ class TestUserStats(unittest.TestCase):
             trove_language=[],
         )
         stats.addCommit(newcommit, commit_datetime, project)
-        self.assertEqual(stats.general[0].commits[0],
-                         {'lines': 3, 'number': 1, 'language': None})
+        assert stats.general[0].commits[0] == \
+                         {'lines': 3, 'number': 1, 'language': None}
         unified_diff.reset_mock()
         with h.push_config(config, **{'userstats.count_lines_of_code': 'false'}):
             stats.addCommit(newcommit, commit_datetime, project)
-        self.assertEqual(stats.general[0].commits[0],
-                         {'lines': 3, 'number': 2, 'language': None})
+        assert stats.general[0].commits[0] == \
+                         {'lines': 3, 'number': 2, 'language': None}
         assert not unified_diff.called