You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by di...@apache.org on 2022/09/21 16:04:45 UTC

[allura] branch dw/8455-part2 created (now 85f479ba3)

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

dill0wn pushed a change to branch dw/8455-part2
in repository https://gitbox.apache.org/repos/asf/allura.git


      at 85f479ba3 fixup! [#8455] converted the remaining modules fully to pytest

This branch includes the following new commits:

     new dd33f12e1 [#8455] ran nose2pytest on Forge* and AlluraTest modules
     new dfb1887fc [#8455] converted the remaining modules fully to pytest
     new 85f479ba3 fixup! [#8455] converted the remaining modules fully to pytest

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[allura] 01/03: [#8455] ran nose2pytest on Forge* and AlluraTest modules

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dill0wn pushed a commit to branch dw/8455-part2
in repository https://gitbox.apache.org/repos/asf/allura.git

commit dd33f12e1bf93d04e424fb9057c09f45bec184a0
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Sep 16 13:33:22 2022 +0000

    [#8455] ran nose2pytest on Forge* and AlluraTest modules
---
 Allura/allura/tests/functional/test_admin.py       |   2 +-
 Allura/allura/tests/functional/test_auth.py        |   2 +-
 Allura/allura/tests/functional/test_discuss.py     |   2 +-
 Allura/allura/tests/functional/test_feeds.py       |   2 +-
 Allura/allura/tests/functional/test_gravatar.py    |   2 +-
 Allura/allura/tests/functional/test_home.py        |   2 +-
 Allura/allura/tests/functional/test_nav.py         |   2 +-
 .../allura/tests/functional/test_neighborhood.py   |   2 +-
 Allura/allura/tests/functional/test_newforge.py    |   2 +-
 .../tests/functional/test_personal_dashboard.py    |   2 +-
 Allura/allura/tests/functional/test_rest.py        |   2 +-
 Allura/allura/tests/functional/test_root.py        |   2 +-
 Allura/allura/tests/functional/test_search.py      |   2 +-
 Allura/allura/tests/functional/test_site_admin.py  |   2 +-
 Allura/allura/tests/functional/test_static.py      |   2 +-
 Allura/allura/tests/functional/test_subscriber.py  |   2 +-
 Allura/allura/tests/functional/test_tool_list.py   |   2 +-
 .../allura/tests/functional/test_trovecategory.py  |   2 +-
 .../allura/tests/functional/test_user_profile.py   |   2 +-
 Allura/allura/tests/model/test_auth.py             |   2 +-
 Allura/allura/tests/model/test_filesystem.py       |   2 +-
 Allura/allura/tests/model/test_notification.py     |   2 +-
 Allura/allura/tests/model/test_repo.py             |   2 +-
 Allura/allura/tests/model/test_timeline.py         |   2 +-
 .../tests/scripts/test_create_sitemap_files.py     |   2 +-
 .../allura/tests/scripts/test_delete_projects.py   |   2 +-
 Allura/allura/tests/scripts/test_misc_scripts.py   |   2 +-
 Allura/allura/tests/scripts/test_reindexes.py      |   2 +-
 .../tests/templates/jinja_master/test_lib.py       |   2 +-
 Allura/allura/tests/test_app.py                    |   2 +-
 Allura/allura/tests/test_commands.py               |   2 +-
 Allura/allura/tests/test_decorators.py             |   2 +-
 Allura/allura/tests/test_diff.py                   |   2 +-
 Allura/allura/tests/test_dispatch.py               |   2 +-
 Allura/allura/tests/test_globals.py                |   2 +-
 Allura/allura/tests/test_helpers.py                |   2 +-
 Allura/allura/tests/test_mail_util.py              |   2 +-
 Allura/allura/tests/test_markdown.py               |   2 +-
 Allura/allura/tests/test_middlewares.py            |   2 +-
 Allura/allura/tests/test_multifactor.py            |   2 +-
 Allura/allura/tests/test_plugin.py                 |   2 +-
 Allura/allura/tests/test_scripttask.py             |   2 +-
 Allura/allura/tests/test_security.py               |   2 +-
 Allura/allura/tests/test_tasks.py                  |   2 +-
 Allura/allura/tests/test_utils.py                  |   2 +-
 Allura/allura/tests/test_validators.py             |   2 +-
 Allura/allura/tests/test_webhooks.py               |   2 +-
 .../test_discussion_moderation_controller.py       |   2 +-
 Allura/allura/tests/unit/phone/test_nexmo.py       |   2 +-
 .../allura/tests/unit/phone/test_phone_service.py  |   2 +-
 Allura/allura/tests/unit/spam/test_akismet.py      |   2 +-
 Allura/allura/tests/unit/spam/test_spam_filter.py  |   2 +-
 .../allura/tests/unit/spam/test_stopforumspam.py   |   2 +-
 Allura/allura/tests/unit/test_app.py               |   2 +-
 Allura/allura/tests/unit/test_artifact.py          |   2 +-
 Allura/allura/tests/unit/test_discuss.py           |   2 +-
 Allura/allura/tests/unit/test_helpers/test_ago.py  |   2 +-
 .../tests/unit/test_helpers/test_set_context.py    |   2 +-
 .../allura/tests/unit/test_ldap_auth_provider.py   |   2 +-
 Allura/allura/tests/unit/test_mixins.py            |   2 +-
 .../allura/tests/unit/test_package_path_loader.py  |   2 +-
 Allura/allura/tests/unit/test_post_model.py        |   2 +-
 Allura/allura/tests/unit/test_project.py           |   2 +-
 Allura/allura/tests/unit/test_repo.py              |   2 +-
 Allura/allura/tests/unit/test_session.py           |   2 +-
 Allura/allura/tests/unit/test_sitemapentry.py      |   2 +-
 Allura/allura/tests/unit/test_solr.py              |   2 +-
 AlluraTest/alluratest/controller.py                |   2 +-
 .../alluratest}/pytest_helpers.py                  |   0
 .../forgeactivity/tests/functional/test_rest.py    |  18 +-
 .../forgeactivity/tests/functional/test_root.py    |  82 +--
 ForgeBlog/forgeblog/tests/functional/test_feeds.py |  12 +-
 ForgeBlog/forgeblog/tests/functional/test_rest.py  |  92 ++--
 ForgeBlog/forgeblog/tests/functional/test_root.py  |  12 +-
 ForgeBlog/forgeblog/tests/test_app.py              |  26 +-
 ForgeBlog/forgeblog/tests/test_commands.py         |  18 +-
 ForgeBlog/forgeblog/tests/unit/test_blog_post.py   |  20 +-
 ForgeChat/forgechat/tests/functional/test_root.py  |   6 +-
 .../forgediscussion/tests/functional/test_forum.py |  92 ++--
 .../tests/functional/test_import.py                |  20 +-
 .../forgediscussion/tests/functional/test_rest.py  | 176 +++----
 ForgeDiscussion/forgediscussion/tests/test_app.py  |  40 +-
 .../forgefeedback/tests/functional/test_root.py    |  12 +-
 .../forgefeedback/tests/test_feedback_roles.py     |   8 +-
 .../forgefeedback/tests/unit/test_feedback.py      |  10 +-
 .../tests/unit/test_root_controller.py             |   2 +-
 .../forgefiles/tests/functional/test_root.py       |   8 +-
 ForgeFiles/forgefiles/tests/model/test_files.py    |  16 +-
 ForgeFiles/forgefiles/tests/test_files_roles.py    |   8 +-
 ForgeGit/forgegit/tests/functional/test_auth.py    |   4 +-
 .../forgegit/tests/functional/test_controllers.py  | 204 ++++----
 ForgeGit/forgegit/tests/model/test_repository.py   | 148 +++---
 ForgeGit/forgegit/tests/test_git_app.py            |   2 +-
 .../forgeimporters/github/tests/test_utils.py      |  36 +-
 .../forgeimporters/github/tests/test_wiki.py       | 140 +++---
 .../tests/github/functional/test_github.py         |  14 +-
 ForgeImporters/forgeimporters/tests/test_base.py   |  14 +-
 ForgeLink/forgelink/tests/functional/test_rest.py  |  26 +-
 ForgeLink/forgelink/tests/functional/test_root.py  |  30 +-
 ForgeLink/forgelink/tests/test_app.py              |   2 +-
 ForgeSVN/forgesvn/tests/functional/test_auth.py    |  14 +-
 .../forgesvn/tests/functional/test_controllers.py  |  64 +--
 ForgeSVN/forgesvn/tests/model/test_repository.py   | 131 +++--
 .../forgesvn/tests/model/test_svnimplementation.py |  30 +-
 ForgeSVN/forgesvn/tests/test_svn_app.py            |   4 +-
 ForgeSVN/forgesvn/tests/test_tasks.py              |   2 +-
 .../forgeshorturl/tests/functional/test.py         |  12 +-
 .../tests/command/test_fix_discussion.py           |  16 +-
 .../forgetracker/tests/functional/test_rest.py     |  54 +-
 .../forgetracker/tests/functional/test_root.py     | 548 ++++++++++-----------
 ForgeTracker/forgetracker/tests/test_app.py        |  38 +-
 .../forgetracker/tests/unit/test_globals_model.py  |  40 +-
 .../tests/unit/test_milestone_controller.py        |   2 +-
 .../tests/unit/test_root_controller.py             |   2 +-
 .../forgetracker/tests/unit/test_search.py         |   4 +-
 .../forgetracker/tests/unit/test_ticket_model.py   | 112 ++---
 ForgeWiki/forgewiki/tests/functional/test_rest.py  |  50 +-
 ForgeWiki/forgewiki/tests/functional/test_root.py  | 100 ++--
 ForgeWiki/forgewiki/tests/test_app.py              |  28 +-
 ForgeWiki/forgewiki/tests/test_wiki_roles.py       |  18 +-
 120 files changed, 1351 insertions(+), 1352 deletions(-)

diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index b5f39a393..a140f1701 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -32,7 +32,7 @@ import six
 
 import allura
 from allura.tests import TestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from allura.tests import decorators as td
 from allura.tests.decorators import audits, out_audits
 from alluratest.controller import TestRestApiBase, setup_trove_categories
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index ae0e79f16..7be1a4857 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -45,7 +45,7 @@ import oauth2
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura.tests.decorators import audits, out_audits
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from alluratest.controller import setup_trove_categories, TestRestApiBase
 from allura import model as M
 from allura.lib import plugin
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index a2442074a..8adb1a1af 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -25,7 +25,7 @@ from allura.tests import TestController
 from allura import model as M
 from allura.lib import helpers as h
 from tg import config
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_feeds.py b/Allura/allura/tests/functional/test_feeds.py
index 4baf5f9d0..e795f95a9 100644
--- a/Allura/allura/tests/functional/test_feeds.py
+++ b/Allura/allura/tests/functional/test_feeds.py
@@ -20,7 +20,7 @@ from formencode.variabledecode import variable_encode
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura.lib import helpers as h
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_gravatar.py b/Allura/allura/tests/functional/test_gravatar.py
index fdec13eb1..2886df357 100644
--- a/Allura/allura/tests/functional/test_gravatar.py
+++ b/Allura/allura/tests/functional/test_gravatar.py
@@ -23,7 +23,7 @@ from mock import patch
 
 from allura.tests import TestController
 import allura.lib.gravatar as gravatar
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_home.py b/Allura/allura/tests/functional/test_home.py
index 07a149dbb..a27febbea 100644
--- a/Allura/allura/tests/functional/test_home.py
+++ b/Allura/allura/tests/functional/test_home.py
@@ -27,7 +27,7 @@ import allura
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_nav.py b/Allura/allura/tests/functional/test_nav.py
index 840a97969..e7113cc77 100644
--- a/Allura/allura/tests/functional/test_nav.py
+++ b/Allura/allura/tests/functional/test_nav.py
@@ -22,7 +22,7 @@ from tg import app_globals as g
 
 from allura.tests import TestController
 from allura.lib import helpers as h
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index ac7ee3c9d..b123cb7eb 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -37,7 +37,7 @@ from allura.tests import decorators as td
 from allura.lib import helpers as h
 from allura.lib import utils
 from alluratest.controller import setup_trove_categories
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_newforge.py b/Allura/allura/tests/functional/test_newforge.py
index 1e95a38cb..83470c1e4 100644
--- a/Allura/allura/tests/functional/test_newforge.py
+++ b/Allura/allura/tests/functional/test_newforge.py
@@ -21,7 +21,7 @@ from six.moves.urllib.parse import quote
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_personal_dashboard.py b/Allura/allura/tests/functional/test_personal_dashboard.py
index 428afb029..c1f7d3cb3 100644
--- a/Allura/allura/tests/functional/test_personal_dashboard.py
+++ b/Allura/allura/tests/functional/test_personal_dashboard.py
@@ -30,7 +30,7 @@ from allura.tests import TestController
 from allura.tests import decorators as td
 from alluratest.controller import setup_global_objects, setup_unit_test
 from forgetracker.tests.functional.test_root import TrackerTestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index 0be71b396..c2a8cef8b 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -31,7 +31,7 @@ from alluratest.controller import TestRestApiBase
 from allura.lib import helpers as h
 from allura.lib.exceptions import Invalid
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_root.py b/Allura/allura/tests/functional/test_root.py
index 95a1ea15b..0b2af9c99 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -41,7 +41,7 @@ from allura.tests import TestController
 from allura import model as M
 from allura.lib import helpers as h
 from alluratest.controller import setup_trove_categories
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_search.py b/Allura/allura/tests/functional/test_search.py
index 52fba8d7f..a24bc0497 100644
--- a/Allura/allura/tests/functional/test_search.py
+++ b/Allura/allura/tests/functional/test_search.py
@@ -24,7 +24,7 @@ from allura.tests import TestController
 from allura.tests.decorators import with_tool
 
 from forgewiki.model import Page
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 7ca541362..ec743bb1f 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -33,7 +33,7 @@ from allura.lib import helpers as h
 from allura.lib.decorators import task
 from allura.lib.plugin import LocalAuthenticationProvider
 import six
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_static.py b/Allura/allura/tests/functional/test_static.py
index 7912e425c..38e4ba760 100644
--- a/Allura/allura/tests/functional/test_static.py
+++ b/Allura/allura/tests/functional/test_static.py
@@ -17,7 +17,7 @@
 
 
 from allura.tests import TestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_subscriber.py b/Allura/allura/tests/functional/test_subscriber.py
index 02a273cfc..32333f92d 100644
--- a/Allura/allura/tests/functional/test_subscriber.py
+++ b/Allura/allura/tests/functional/test_subscriber.py
@@ -19,7 +19,7 @@ from allura.tests import TestController
 from allura.tests import decorators as td
 from allura.model.notification import Mailbox
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_tool_list.py b/Allura/allura/tests/functional/test_tool_list.py
index 8e4bfafb1..3562463b4 100644
--- a/Allura/allura/tests/functional/test_tool_list.py
+++ b/Allura/allura/tests/functional/test_tool_list.py
@@ -17,7 +17,7 @@
 
 from allura.tests import TestController
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_trovecategory.py b/Allura/allura/tests/functional/test_trovecategory.py
index 8588607aa..76473d3d7 100644
--- a/Allura/allura/tests/functional/test_trovecategory.py
+++ b/Allura/allura/tests/functional/test_trovecategory.py
@@ -26,7 +26,7 @@ from allura.lib import helpers as h
 from allura.tests import TestController
 from alluratest.controller import setup_trove_categories
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index e4df160e1..353a99fa7 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -23,7 +23,7 @@ from alluratest.controller import TestRestApiBase
 from allura.model import Project, User
 from allura.tests import decorators as td
 from allura.tests import TestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 class TestUserProfileSections(TestController):
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 7f48c49bc..b4e5e80de 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -42,7 +42,7 @@ from allura.lib import helpers as h
 from allura.lib import plugin
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects, setup_functional_test
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def setup_method():
diff --git a/Allura/allura/tests/model/test_filesystem.py b/Allura/allura/tests/model/test_filesystem.py
index df0e5b7d5..fe88d8aa7 100644
--- a/Allura/allura/tests/model/test_filesystem.py
+++ b/Allura/allura/tests/model/test_filesystem.py
@@ -28,7 +28,7 @@ from webob import Request, Response
 
 from allura import model as M
 from alluratest.controller import setup_unit_test
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 class File(M.File):
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index 7e0b8ed3d..33d2547fd 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -31,7 +31,7 @@ from allura.model.notification import MailFooter
 from allura.lib import helpers as h
 from allura.tests import decorators as td
 from forgewiki import model as WM
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/model/test_repo.py b/Allura/allura/tests/model/test_repo.py
index 873b411c8..84d26bdf2 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -29,7 +29,7 @@ from tg import config
 from alluratest.controller import setup_basic_test, setup_global_objects
 from allura import model as M
 from allura.lib import helpers as h
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/model/test_timeline.py b/Allura/allura/tests/model/test_timeline.py
index 3d8bc26e7..00e7ea069 100644
--- a/Allura/allura/tests/model/test_timeline.py
+++ b/Allura/allura/tests/model/test_timeline.py
@@ -20,7 +20,7 @@ from alluratest.tools import assert_equal
 from allura import model as M
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/scripts/test_create_sitemap_files.py b/Allura/allura/tests/scripts/test_create_sitemap_files.py
index c5835109f..13c853940 100644
--- a/Allura/allura/tests/scripts/test_create_sitemap_files.py
+++ b/Allura/allura/tests/scripts/test_create_sitemap_files.py
@@ -27,7 +27,7 @@ from alluratest.controller import setup_basic_test
 from allura import model as M
 from allura.lib import helpers as h
 from allura.scripts.create_sitemap_files import CreateSitemapFiles
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/scripts/test_delete_projects.py b/Allura/allura/tests/scripts/test_delete_projects.py
index 57c219f54..d9414358f 100644
--- a/Allura/allura/tests/scripts/test_delete_projects.py
+++ b/Allura/allura/tests/scripts/test_delete_projects.py
@@ -25,7 +25,7 @@ from allura.tests.decorators import audits, out_audits, with_user_project
 from allura import model as M
 from allura.scripts import delete_projects
 from allura.lib import plugin
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/scripts/test_misc_scripts.py b/Allura/allura/tests/scripts/test_misc_scripts.py
index 8ebbba848..83c8c145e 100644
--- a/Allura/allura/tests/scripts/test_misc_scripts.py
+++ b/Allura/allura/tests/scripts/test_misc_scripts.py
@@ -22,7 +22,7 @@ from allura.scripts.clear_old_notifications import ClearOldNotifications
 from alluratest.controller import setup_basic_test
 from allura import model as M
 from ming.odm import session
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/scripts/test_reindexes.py b/Allura/allura/tests/scripts/test_reindexes.py
index 53a51f04a..c6da7ad62 100644
--- a/Allura/allura/tests/scripts/test_reindexes.py
+++ b/Allura/allura/tests/scripts/test_reindexes.py
@@ -22,7 +22,7 @@ from allura.scripts.reindex_users import ReindexUsers
 from allura.tests.decorators import assert_logmsg_and_no_warnings_or_errors
 from alluratest.controller import setup_basic_test
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/templates/jinja_master/test_lib.py b/Allura/allura/tests/templates/jinja_master/test_lib.py
index f3eea9edd..8c46da06b 100644
--- a/Allura/allura/tests/templates/jinja_master/test_lib.py
+++ b/Allura/allura/tests/templates/jinja_master/test_lib.py
@@ -22,7 +22,7 @@ from alluratest.tools import assert_equal
 import ming
 from allura.config.app_cfg import ForgeConfig, AlluraJinjaRenderer
 from alluratest.controller import setup_basic_test
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def strip_space(s):
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index b93170a8e..024c12fd3 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -26,7 +26,7 @@ from alluratest.tools import with_setup
 from allura import app
 from allura.lib.app_globals import Icon
 from allura.lib import mail_util
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def setup_method():
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index 84bac7a10..f7440e3a1 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -36,7 +36,7 @@ from allura.command import base, script, set_neighborhood_features, \
 from allura import model as M
 from allura.lib.exceptions import InvalidNBFeatureValueError
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 test_config = pkg_resources.resource_filename(
diff --git a/Allura/allura/tests/test_decorators.py b/Allura/allura/tests/test_decorators.py
index 033e5c41a..71b70d019 100644
--- a/Allura/allura/tests/test_decorators.py
+++ b/Allura/allura/tests/test_decorators.py
@@ -21,7 +21,7 @@ import random
 import gc
 
 from alluratest.tools import assert_equal, assert_not_equal
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from allura.lib.decorators import task, memoize
 from alluratest.controller import setup_basic_test, setup_global_objects
 
diff --git a/Allura/allura/tests/test_diff.py b/Allura/allura/tests/test_diff.py
index d128386b0..1485bc1a8 100644
--- a/Allura/allura/tests/test_diff.py
+++ b/Allura/allura/tests/test_diff.py
@@ -18,7 +18,7 @@
 import unittest
 
 from allura.lib.diff import HtmlSideBySideDiff
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/test_dispatch.py b/Allura/allura/tests/test_dispatch.py
index 265fdd187..983ffac72 100644
--- a/Allura/allura/tests/test_dispatch.py
+++ b/Allura/allura/tests/test_dispatch.py
@@ -16,7 +16,7 @@
 #       under the License.
 
 from allura.tests import TestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 app = None
 
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 389c7a228..29b318027 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -43,7 +43,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.lib.app_globals import ForgeMarkdown
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 from forgewiki import model as WM
 from forgeblog import model as BM
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index dbd359e33..6e03cb8c5 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -37,7 +37,7 @@ from allura.lib.search import inject_user
 from allura.lib.security import has_access
 from allura.lib.security import Credentials
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from alluratest.controller import setup_basic_test
 import six
 
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index f1ad21d09..33e80bfb0 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -37,7 +37,7 @@ from allura.lib.mail_util import (
     _parse_message_id,
 )
 from allura.lib.exceptions import AddressException
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from allura.tests import decorators as td
 import six
 
diff --git a/Allura/allura/tests/test_markdown.py b/Allura/allura/tests/test_markdown.py
index 5334aa4d6..6878143f1 100644
--- a/Allura/allura/tests/test_markdown.py
+++ b/Allura/allura/tests/test_markdown.py
@@ -19,7 +19,7 @@ import unittest
 import mock
 
 from allura.lib import markdown_extensions as mde
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/test_middlewares.py b/Allura/allura/tests/test_middlewares.py
index 1f8e78a79..b48e27603 100644
--- a/Allura/allura/tests/test_middlewares.py
+++ b/Allura/allura/tests/test_middlewares.py
@@ -19,7 +19,7 @@ from mock import MagicMock, patch
 from datadiff.tools import assert_equal
 from alluratest.tools import assert_not_equal
 from allura.lib.custom_middleware import CORSMiddleware
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/test_multifactor.py b/Allura/allura/tests/test_multifactor.py
index e007b0adf..ba7780f3b 100644
--- a/Allura/allura/tests/test_multifactor.py
+++ b/Allura/allura/tests/test_multifactor.py
@@ -32,7 +32,7 @@ from allura.lib.multifactor import GoogleAuthenticatorFile, TotpService, Mongodb
 from allura.lib.multifactor import GoogleAuthenticatorPamFilesystemTotpService
 from allura.lib.multifactor import RecoveryCodeService, MongodbRecoveryCodeService
 from allura.lib.multifactor import GoogleAuthenticatorPamFilesystemRecoveryCodeService
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py
index f11eae8d7..cfe441693 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -45,7 +45,7 @@ from allura.lib.exceptions import ProjectConflict, ProjectShortnameInvalid
 from allura.tests.decorators import audits
 from allura.tests.exclude_from_rewrite_hook import ThemeProviderTestApp
 from alluratest.controller import setup_basic_test, setup_global_objects
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def setup_module(module):
diff --git a/Allura/allura/tests/test_scripttask.py b/Allura/allura/tests/test_scripttask.py
index f8576bbf8..ae284a1e9 100644
--- a/Allura/allura/tests/test_scripttask.py
+++ b/Allura/allura/tests/test_scripttask.py
@@ -19,7 +19,7 @@ import unittest
 import mock
 
 from allura.scripts.scripttask import ScriptTask
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/test_security.py b/Allura/allura/tests/test_security.py
index 5fe92b964..f6771f3aa 100644
--- a/Allura/allura/tests/test_security.py
+++ b/Allura/allura/tests/test_security.py
@@ -28,7 +28,7 @@ from forgewiki import model as WM
 from allura.lib.security import HIBPClientError, HIBPClient
 from mock import Mock, patch
 from requests.exceptions import Timeout
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def _allow(obj, role, perm):
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 429effd80..2aeef658d 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -52,7 +52,7 @@ from allura.tasks import repo_tasks
 from allura.tasks import export_tasks
 from allura.tasks import admin_tasks
 from allura.tests import decorators as td
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 from allura.tests.exclude_from_rewrite_hook import raise_compound_exception
 from allura.lib.decorators import event_handler, task
 
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 6e7fca1cc..4c22c1a93 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -44,7 +44,7 @@ from alluratest.controller import setup_unit_test
 from allura import model as M
 from allura.lib import utils
 from allura.lib import helpers as h
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @patch.dict('allura.lib.utils.tg.config', clear=True, foo='bar', baz='true')
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index 2e0f5af65..a9c011368 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -24,7 +24,7 @@ from allura.lib import validators as v
 from allura.lib.decorators import task
 from alluratest.controller import setup_basic_test
 from allura.websetup.bootstrap import create_user
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def _setup_method():
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 8237847d6..3b11f5e05 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -49,7 +49,7 @@ from alluratest.controller import (
     TestRestApiBase,
 )
 import six
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 # important to be distinct from 'test' and 'test2' which ForgeGit and
diff --git a/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py b/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
index 72abd8ed4..3ad4ed8df 100644
--- a/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
+++ b/Allura/allura/tests/unit/controllers/test_discussion_moderation_controller.py
@@ -24,7 +24,7 @@ from allura.tests.unit.factories import create_post, create_discussion
 from allura import model
 from allura.controllers.discuss import ModerationController
 from allura.tests.unit import patches
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/phone/test_nexmo.py b/Allura/allura/tests/unit/phone/test_nexmo.py
index 2bcff5cfa..290273946 100644
--- a/Allura/allura/tests/unit/phone/test_nexmo.py
+++ b/Allura/allura/tests/unit/phone/test_nexmo.py
@@ -19,7 +19,7 @@ import json
 from mock import patch
 from datadiff.tools import assert_equal
 from alluratest.tools import assert_in, assert_not_in
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 from allura.lib.phone.nexmo import NexmoPhoneService
 
diff --git a/Allura/allura/tests/unit/phone/test_phone_service.py b/Allura/allura/tests/unit/phone/test_phone_service.py
index fe5b2844e..e4af19908 100644
--- a/Allura/allura/tests/unit/phone/test_phone_service.py
+++ b/Allura/allura/tests/unit/phone/test_phone_service.py
@@ -19,7 +19,7 @@ from alluratest.tools import assert_true
 from datadiff.tools import assert_equal
 
 from allura.lib.phone import PhoneService
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 class MockPhoneService(PhoneService):
diff --git a/Allura/allura/tests/unit/spam/test_akismet.py b/Allura/allura/tests/unit/spam/test_akismet.py
index bee8403cd..2c6e2af31 100644
--- a/Allura/allura/tests/unit/spam/test_akismet.py
+++ b/Allura/allura/tests/unit/spam/test_akismet.py
@@ -26,7 +26,7 @@ from datetime import datetime
 from bson import ObjectId
 
 from allura.lib.spam.akismetfilter import AKISMET_AVAILABLE, AkismetSpamFilter
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @unittest.skipIf(not AKISMET_AVAILABLE, "Akismet not available")
diff --git a/Allura/allura/tests/unit/spam/test_spam_filter.py b/Allura/allura/tests/unit/spam/test_spam_filter.py
index 99f6ce1a9..f907b41ef 100644
--- a/Allura/allura/tests/unit/spam/test_spam_filter.py
+++ b/Allura/allura/tests/unit/spam/test_spam_filter.py
@@ -26,7 +26,7 @@ from allura import model as M
 from allura.model.artifact import SpamCheckResult
 from alluratest.controller import setup_basic_test
 from forgewiki import model as WM
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 class MockFilter(SpamFilter):
diff --git a/Allura/allura/tests/unit/spam/test_stopforumspam.py b/Allura/allura/tests/unit/spam/test_stopforumspam.py
index 2037ddde8..7a1bd31d7 100644
--- a/Allura/allura/tests/unit/spam/test_stopforumspam.py
+++ b/Allura/allura/tests/unit/spam/test_stopforumspam.py
@@ -22,7 +22,7 @@ from bson import ObjectId
 from alluratest.tools import assert_equal
 
 from allura.lib.spam.stopforumspamfilter import StopForumSpamSpamFilter
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 2a374f415..65d000fae 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -22,7 +22,7 @@ from allura import model
 from allura.tests.unit import WithDatabase
 from allura.tests.unit.patches import fake_app_patch
 from allura.tests.unit.factories import create_project, create_app_config
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_artifact.py b/Allura/allura/tests/unit/test_artifact.py
index 801a29fef..1cbe17f47 100644
--- a/Allura/allura/tests/unit/test_artifact.py
+++ b/Allura/allura/tests/unit/test_artifact.py
@@ -18,7 +18,7 @@
 import unittest
 
 from allura import model as M
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_discuss.py b/Allura/allura/tests/unit/test_discuss.py
index 9cb225e40..6078dff49 100644
--- a/Allura/allura/tests/unit/test_discuss.py
+++ b/Allura/allura/tests/unit/test_discuss.py
@@ -18,7 +18,7 @@
 from allura import model as M
 from allura.tests.unit import WithDatabase
 from allura.tests.unit.patches import fake_app_patch
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_helpers/test_ago.py b/Allura/allura/tests/unit/test_helpers/test_ago.py
index 7fef39014..a8e4c9044 100644
--- a/Allura/allura/tests/unit/test_helpers/test_ago.py
+++ b/Allura/allura/tests/unit/test_helpers/test_ago.py
@@ -21,7 +21,7 @@ from mock import patch
 from alluratest.tools import assert_equal
 
 from allura.lib import helpers
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_helpers/test_set_context.py b/Allura/allura/tests/unit/test_helpers/test_set_context.py
index 3468ceed0..9e6999231 100644
--- a/Allura/allura/tests/unit/test_helpers/test_set_context.py
+++ b/Allura/allura/tests/unit/test_helpers/test_set_context.py
@@ -26,7 +26,7 @@ from allura.tests.unit import patches
 from allura.tests.unit.factories import (create_project,
                                          create_app_config,
                                          create_neighborhood)
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_ldap_auth_provider.py b/Allura/allura/tests/unit/test_ldap_auth_provider.py
index d94430188..bc17ce9a5 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -32,7 +32,7 @@ from allura.lib import plugin
 from allura.lib import helpers as h
 from allura import model as M
 import six
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_mixins.py b/Allura/allura/tests/unit/test_mixins.py
index f4e50aafe..775ff0358 100644
--- a/Allura/allura/tests/unit/test_mixins.py
+++ b/Allura/allura/tests/unit/test_mixins.py
@@ -17,7 +17,7 @@
 
 from mock import Mock
 from allura.model import VotableArtifact
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_package_path_loader.py b/Allura/allura/tests/unit/test_package_path_loader.py
index 5c39771f6..5aec5fea2 100644
--- a/Allura/allura/tests/unit/test_package_path_loader.py
+++ b/Allura/allura/tests/unit/test_package_path_loader.py
@@ -25,7 +25,7 @@ import mock
 from tg import config
 
 from allura.lib.package_path_loader import PackagePathLoader
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_post_model.py b/Allura/allura/tests/unit/test_post_model.py
index e1f7504ed..eca936d1e 100644
--- a/Allura/allura/tests/unit/test_post_model.py
+++ b/Allura/allura/tests/unit/test_post_model.py
@@ -22,7 +22,7 @@ from allura import model as M
 from allura.tests.unit import WithDatabase
 from allura.tests.unit import patches
 from allura.tests.unit.factories import create_post
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_project.py b/Allura/allura/tests/unit/test_project.py
index 3fefa5fe1..2fb093643 100644
--- a/Allura/allura/tests/unit/test_project.py
+++ b/Allura/allura/tests/unit/test_project.py
@@ -23,7 +23,7 @@ from tg import config
 from allura import model as M
 from allura.lib import helpers as h
 from allura.app import SitemapEntry
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index df862d547..a33d8c644 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -31,7 +31,7 @@ from allura.model.repository import zipdir, prefix_paths_union
 from allura.model.repo_refresh import (
     _group_commits,
 )
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_session.py b/Allura/allura/tests/unit/test_session.py
index cb7f02f7d..d7899302f 100644
--- a/Allura/allura/tests/unit/test_session.py
+++ b/Allura/allura/tests/unit/test_session.py
@@ -28,7 +28,7 @@ from allura.model.session import (
     ArtifactSessionExtension,
     substitute_extensions,
 )
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 def test_extensions_cm():
diff --git a/Allura/allura/tests/unit/test_sitemapentry.py b/Allura/allura/tests/unit/test_sitemapentry.py
index e4e56deec..ea38b10b7 100644
--- a/Allura/allura/tests/unit/test_sitemapentry.py
+++ b/Allura/allura/tests/unit/test_sitemapentry.py
@@ -19,7 +19,7 @@ import unittest
 from mock import Mock
 
 from allura.app import SitemapEntry
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/Allura/allura/tests/unit/test_solr.py b/Allura/allura/tests/unit/test_solr.py
index cc73cdb6f..fa23bc135 100644
--- a/Allura/allura/tests/unit/test_solr.py
+++ b/Allura/allura/tests/unit/test_solr.py
@@ -26,7 +26,7 @@ from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test
 from allura.lib.solr import Solr, escape_solr_arg
 from allura.lib.search import search_app, SearchIndexable
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 @with_nose_compatibility
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 8f3099b39..a78e3d233 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -17,7 +17,7 @@
 
 """Unit and functional test suite for allura."""
 import os
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 import six.moves.urllib.request
 import six.moves.urllib.parse
 import six.moves.urllib.error
diff --git a/Allura/allura/tests/pytest_helpers.py b/AlluraTest/alluratest/pytest_helpers.py
similarity index 100%
rename from Allura/allura/tests/pytest_helpers.py
rename to AlluraTest/alluratest/pytest_helpers.py
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_rest.py b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
index cb11dc9b2..d20166d5f 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_rest.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
@@ -42,13 +42,13 @@ class TestActivityHasAccessAPI(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/activity/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/activity/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -64,15 +64,15 @@ class TestActivityHasAccessAPI(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/activity/has_access?user=test-admin&perm=admin',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/activity/has_access?user=test-user&perm=admin',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
 
     def test_user_api(self):
         r = self.api_get('/rest/u/test-user/activity')
-        assert_equal(r.status_int, 200)
\ No newline at end of file
+        assert r.status_int == 200
\ No newline at end of file
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_root.py b/ForgeActivity/forgeactivity/tests/functional/test_root.py
index 2948e560b..cb90360d1 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -95,9 +95,9 @@ class TestActivityController(TestController):
         })]
         r = self.app.get('/p/test/activity/')
         timeline = r.html.find('ul', 'timeline')
-        assert_equal(1, len(timeline.findAll('li')))
+        assert 1 == len(timeline.findAll('li'))
         activity = timeline.find('li')
-        assert_equal(activity.time['title'], "2013-12-04 21:48:19")
+        assert activity.time['title'] == "2013-12-04 21:48:19"
         h1 = """\
         <h1>
          <img alt="Administrator 1" class="emboss x32 avatar" src="/u/test-admin/user_icon" title="Administrator 1"/>
@@ -114,13 +114,13 @@ class TestActivityController(TestController):
          </a>
         </h1>
         """
-        assert_equal(dedent(h1), activity.h1.prettify())
+        assert dedent(h1) == activity.h1.prettify()
         p = """\
         <p>
          Just wanted to leave a comment on this...
         </p>
         """
-        assert_equal(dedent(p), activity.p.prettify())
+        assert dedent(p) == activity.p.prettify()
 
     @td.with_tool('u/test-user-1', 'activity')
     @td.with_user_project('test-user-1')
@@ -170,11 +170,11 @@ class TestActivityController(TestController):
             create_timeline.side_effect = orig_create_timeline
             M.MonQTask.run_ready()
             # 3 aggregations: 1 actor, 1 follower, 1 project
-            assert_equal(create_timeline.call_count, 3)
+            assert create_timeline.call_count == 3
             create_timeline.reset_mock()
             self.app.get('/u/test-admin/activity/')
             self.app.get('/u/test-user-1/activity/')
-            assert_equal(create_timeline.call_count, 0)
+            assert create_timeline.call_count == 0
 
     @td.with_tool('test', 'activity')
     @patch('forgeactivity.main.g.director')
@@ -213,17 +213,17 @@ class TestActivityController(TestController):
         })]
         r = self.app.get('/p/test/activity/feed.rss')
         timeline = r.xml.find('channel')
-        assert_equal(1, len(timeline.findall('item')))
+        assert 1 == len(timeline.findall('item'))
         activity = timeline.find('item')
-        assert_equal(activity.find('pubDate').text,
+        assert (activity.find('pubDate').text ==
                      'Wed, 04 Dec 2013 21:48:19 -0000')
-        assert_equal(activity.find('title').text,
+        assert (activity.find('title').text ==
                      'Administrator 1 posted a comment on ticket #34')
-        assert_equal(activity.find('description').text,
+        assert (activity.find('description').text ==
                      'Just wanted to leave a comment on this...')
-        assert_equal(activity.find('guid').text,
+        assert (activity.find('guid').text ==
                      'http://localhost/p/test/unicode•º/?limit=25#ed7c')
-        assert_equal(activity.find('link').text,
+        assert (activity.find('link').text ==
                      'http://localhost/p/test/unicode%E2%80%A2%C2%BA/?limit=25#ed7c')
 
     @td.with_tool('test', 'activity')
@@ -244,10 +244,10 @@ class TestActivityController(TestController):
 
         r = self.app.get('/p/test/activity/feed.rss')
         timeline = r.xml.find('channel')
-        assert_equal(1, len(timeline.findall('item')))
+        assert 1 == len(timeline.findall('item'))
         activity = timeline.find('item')
 
-        assert_equal(activity.find('title').text, 'Administrator 1 created ticket #34')
+        assert activity.find('title').text == 'Administrator 1 created ticket #34'
 
     @td.with_tool('u/test-user-1', 'activity')
     @td.with_user_project('test-user-1')
@@ -287,15 +287,15 @@ class TestActivityController(TestController):
         })]
         r = self.app.get('/u/test-user-1/activity/feed.rss')
         timeline = r.xml.find('channel')
-        assert_equal(1, len(timeline.findall('item')))
+        assert 1 == len(timeline.findall('item'))
         activity = timeline.find('item')
-        assert_equal(activity.find('pubDate').text,
+        assert (activity.find('pubDate').text ==
                      'Wed, 04 Dec 2013 21:48:19 -0000')
-        assert_equal(activity.find('title').text,
+        assert (activity.find('title').text ==
                      'Administrator 1 posted a comment on ticket #34')
-        assert_equal(activity.find('description').text,
+        assert (activity.find('description').text ==
                      'Just wanted to leave a comment on this...')
-        assert_equal(activity.find('link').text,
+        assert (activity.find('link').text ==
                      'http://localhost/p/test/tickets/34/?limit=25#ed7c')
 
     @td.with_tool('test', 'activity')
@@ -335,20 +335,20 @@ class TestActivityController(TestController):
         })]
         r = self.app.get('/p/test/activity/feed.atom')
         timeline = r.xml
-        assert_equal(1, len(timeline.findall(
-            '{http://www.w3.org/2005/Atom}entry')))
+        assert 1 == len(timeline.findall(
+            '{http://www.w3.org/2005/Atom}entry'))
         activity = timeline.find('{http://www.w3.org/2005/Atom}entry')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}published').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}published').text ==
             '2013-12-04T21:48:19Z')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}title').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}title').text ==
             'Administrator 1 posted a comment on ticket #34')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}summary').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}summary').text ==
             'Just wanted to leave a comment on this...')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}link').get('href'),
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}link').get('href') ==
             'http://localhost/p/test/tickets/34/?limit=25#ed7c')
 
     @td.with_tool('u/test-user-1', 'activity')
@@ -389,20 +389,20 @@ class TestActivityController(TestController):
         })]
         r = self.app.get('/u/test-user-1/activity/feed.atom')
         timeline = r.xml
-        assert_equal(1, len(timeline.findall(
-            '{http://www.w3.org/2005/Atom}entry')))
+        assert 1 == len(timeline.findall(
+            '{http://www.w3.org/2005/Atom}entry'))
         activity = timeline.find('{http://www.w3.org/2005/Atom}entry')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}published').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}published').text ==
             '2013-12-04T21:48:19Z')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}title').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}title').text ==
             'Administrator 1 posted a comment on ticket #34')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}summary').text,
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}summary').text ==
             'Just wanted to leave a comment on this...')
-        assert_equal(
-            activity.find('{http://www.w3.org/2005/Atom}link').get('href'),
+        assert (
+            activity.find('{http://www.w3.org/2005/Atom}link').get('href') ==
             'http://localhost/p/test/tickets/34/?limit=25#ed7c')
 
     @td.with_tool('u/test-user-1', 'activity')
@@ -459,7 +459,7 @@ class TestActivityController(TestController):
         activity3 = Activity(**dict(activity_data, node_id='User:abc', owner_id='User:abc'))
         ThreadLocalODMSession.flush_all()
         activity_id = str(activity._id)
-        assert_equal(Activity.query.find({'obj.activity_extras.summary': 'Sensitive private info, oops'}).count(), 3)
+        assert Activity.query.find({'obj.activity_extras.summary': 'Sensitive private info, oops'}).count() == 3
 
         self.app.post('/u/test-user-1/activity/delete_item',
                       {'activity_id': activity_id},
@@ -467,4 +467,4 @@ class TestActivityController(TestController):
                       status=200)
         ThreadLocalODMSession.flush_all()
 
-        assert_equal(Activity.query.find({'obj.activity_extras.summary': 'Sensitive private info, oops'}).count(), 0)
+        assert Activity.query.find({'obj.activity_extras.summary': 'Sensitive private info, oops'}).count() == 0
diff --git a/ForgeBlog/forgeblog/tests/functional/test_feeds.py b/ForgeBlog/forgeblog/tests/functional/test_feeds.py
index fde0322f4..530f8bdb4 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_feeds.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_feeds.py
@@ -68,10 +68,10 @@ class TestFeeds(TestController):
     def test_rss_feed_contains_self_link(self):
         r = self.app.get('/blog/feed.rss')
         # atom namespace included
-        assert_in('<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">', r)
+        assert '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' in r
         # ...and atom:link points to feed url
-        assert_in('<atom:link href="http://localhost/blog/feed.rss" '
-                  'rel="self" type="application/rss+xml"></atom:link>', r)
+        assert ('<atom:link href="http://localhost/blog/feed.rss" '
+                  'rel="self" type="application/rss+xml"></atom:link>' in r)
 
     def test_post_feeds(self):
         self._post()
@@ -82,7 +82,7 @@ class TestFeeds(TestController):
         assert 'Nothing to see' in response
         self._post(title='test', text='*sometext*')
         response = self.app.get('/blog/feed')
-        assert_in('&lt;div class="markdown_content"&gt;&lt;p&gt;&lt;em&gt;sometext&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;',
+        assert ('&lt;div class="markdown_content"&gt;&lt;p&gt;&lt;em&gt;sometext&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;' in
                   response)
 
     def test_related_artifacts(self):
@@ -142,7 +142,7 @@ class TestFeeds(TestController):
         ThreadLocalORMSession.flush_all()
 
         resp = self.app.get(h.urlquote("/blog/" + self._blog_date() + "/my-pôst/feed.rss"))
-        assert_in('boring comment', resp)
+        assert 'boring comment' in resp
 
         resp = self.app.get("/blog/feed.rss")
-        assert_not_in('boring comment', resp)
\ No newline at end of file
+        assert 'boring comment' not in resp
\ No newline at end of file
diff --git a/ForgeBlog/forgeblog/tests/functional/test_rest.py b/ForgeBlog/forgeblog/tests/functional/test_rest.py
index a5219f2c3..9e8a87756 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_rest.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_rest.py
@@ -45,21 +45,21 @@ class TestBlogApi(TestRestApiBase):
             'labels': 'label1, label2'
         }
         r = self.api_post('/rest/p/test/blog/', **data)
-        assert_equal(
-            r.location, 'http://localhost/rest/p/test/blog/%s/%s/test/' %
+        assert (
+            r.location == 'http://localhost/rest/p/test/blog/%s/%s/test/' %
             (date.today().strftime("%Y"), date.today().strftime("%m")))
-        assert_equal(r.status_int, 201)
+        assert r.status_int == 201
         url = '/rest' + BM.BlogPost.query.find().first().url()
         r = self.api_get('/rest/p/test/blog/')
-        assert_equal(r.json['posts'][0]['title'], 'test')
-        assert_in(url, r.json['posts'][0]['url'])
+        assert r.json['posts'][0]['title'] == 'test'
+        assert url in r.json['posts'][0]['url']
 
         r = self.api_get(url)
-        assert_equal(r.json['title'], data['title'])
-        assert_equal(r.json['text'], data['text'])
-        assert_equal(r.json['author'], 'test-admin')
-        assert_equal(r.json['state'], data['state'])
-        assert_equal(r.json['labels'], data['labels'].split(','))
+        assert r.json['title'] == data['title']
+        assert r.json['text'] == data['text']
+        assert r.json['author'] == 'test-admin'
+        assert r.json['state'] == data['state']
+        assert r.json['labels'] == data['labels'].split(',')
 
     def test_update_post(self):
         data = {
@@ -69,7 +69,7 @@ class TestBlogApi(TestRestApiBase):
             'labels': 'label1, label2'
         }
         r = self.api_post('/rest/p/test/blog/', **data)
-        assert_equal(r.status_int, 201)
+        assert r.status_int == 201
         url = '/rest' + BM.BlogPost.query.find().first().url()
         data = {
             'text': 'test text2',
@@ -78,10 +78,10 @@ class TestBlogApi(TestRestApiBase):
         }
         self.api_post(url, **data)
         r = self.api_get(url)
-        assert_equal(r.json['title'], 'test')
-        assert_equal(r.json['text'], data['text'])
-        assert_equal(r.json['state'], data['state'])
-        assert_equal(r.json['labels'], data['labels'].split(','))
+        assert r.json['title'] == 'test'
+        assert r.json['text'] == data['text']
+        assert r.json['state'] == data['state']
+        assert r.json['labels'] == data['labels'].split(',')
 
     def test_delete_post(self):
         data = {
@@ -90,7 +90,7 @@ class TestBlogApi(TestRestApiBase):
             'labels': 'label1, label2'
         }
         r = self.api_post('/rest/p/test/blog/', **data)
-        assert_equal(r.status_int, 201)
+        assert r.status_int == 201
         url = '/rest' + BM.BlogPost.query.find().first().url()
         self.api_post(url, delete='')
         r = self.api_get(url, status=404)
@@ -149,16 +149,16 @@ class TestBlogApi(TestRestApiBase):
                       extra_environ={'username': '*anonymous'},
                       status=200)
         r = self.api_get(url)
-        assert_equal(r.json['title'], 'test2')
-        assert_equal(r.json['text'], 'test text2')
-        assert_equal(r.json['state'], 'published')
+        assert r.json['title'] == 'test2'
+        assert r.json['text'] == 'test text2'
+        assert r.json['state'] == 'published'
 
     def test_permission_draft_post(self):
         self.api_post('/rest/p/test/blog/', title='test',
                       text='test text', state='draft')
         r = self.app.get('/rest/p/test/blog/',
                          extra_environ={'username': '*anonymous'})
-        assert_equal(r.json['posts'], [])
+        assert r.json['posts'] == []
         url = '/rest' + BM.BlogPost.query.find().first().url()
         self.app.post(url,
                       params=dict(title='test2', text='test text2',
@@ -172,19 +172,19 @@ class TestBlogApi(TestRestApiBase):
         acl.append(anon_write)
         r = self.app.get('/rest/p/test/blog/',
                          extra_environ={'username': '*anonymous'})
-        assert_equal(r.json['posts'][0]['title'], 'test')
+        assert r.json['posts'][0]['title'] == 'test'
 
     def test_draft_post(self):
         self.api_post('/rest/p/test/blog/', title='test',
                       text='test text', state='draft')
         r = self.app.get('/rest/p/test/blog/',
                          extra_environ={'username': '*anonymous'})
-        assert_equal(r.json['posts'], [])
+        assert r.json['posts'] == []
         url = '/rest' + BM.BlogPost.query.find().first().url()
         self.api_post(url, state='published')
         r = self.app.get('/rest/p/test/blog/',
                          extra_environ={'username': '*anonymous'})
-        assert_equal(r.json['posts'][0]['title'], 'test')
+        assert r.json['posts'][0]['title'] == 'test'
 
     def test_pagination(self):
         self.api_post('/rest/p/test/blog/', title='test1',
@@ -194,23 +194,23 @@ class TestBlogApi(TestRestApiBase):
         self.api_post('/rest/p/test/blog/', title='test3',
                       text='test text3', state='published')
         r = self.api_get('/rest/p/test/blog/', limit='1', page='0')
-        assert_equal(r.json['posts'][0]['title'], 'test3')
-        assert_equal(len(r.json['posts']), 1)
-        assert_equal(r.json['count'], 3)
-        assert_equal(r.json['limit'], 1)
-        assert_equal(r.json['page'], 0)
+        assert r.json['posts'][0]['title'] == 'test3'
+        assert len(r.json['posts']) == 1
+        assert r.json['count'] == 3
+        assert r.json['limit'] == 1
+        assert r.json['page'] == 0
         r = self.api_get('/rest/p/test/blog/', limit='2', page='0')
-        assert_equal(r.json['posts'][0]['title'], 'test3')
-        assert_equal(r.json['posts'][1]['title'], 'test2')
-        assert_equal(len(r.json['posts']), 2)
-        assert_equal(r.json['count'], 3)
-        assert_equal(r.json['limit'], 2)
-        assert_equal(r.json['page'], 0)
+        assert r.json['posts'][0]['title'] == 'test3'
+        assert r.json['posts'][1]['title'] == 'test2'
+        assert len(r.json['posts']) == 2
+        assert r.json['count'] == 3
+        assert r.json['limit'] == 2
+        assert r.json['page'] == 0
         r = self.api_get('/rest/p/test/blog/', limit='1', page='2')
-        assert_equal(r.json['posts'][0]['title'], 'test1')
-        assert_equal(r.json['count'], 3)
-        assert_equal(r.json['limit'], 1)
-        assert_equal(r.json['page'], 2)
+        assert r.json['posts'][0]['title'] == 'test1'
+        assert r.json['count'] == 3
+        assert r.json['limit'] == 1
+        assert r.json['page'] == 2
 
     def test_has_access_no_params(self):
         self.api_get('/rest/p/test/blog/has_access', status=404)
@@ -222,13 +222,13 @@ class TestBlogApi(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/blog/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/blog/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -244,13 +244,13 @@ class TestBlogApi(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/blog/has_access?user=test-admin&perm=post&access_token=ABCDEF',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/blog/has_access?user=*anonymous&perm=admin',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_create_post_limit_by_project(self):
         data = {
diff --git a/ForgeBlog/forgeblog/tests/functional/test_root.py b/ForgeBlog/forgeblog/tests/functional/test_root.py
index 11d5a7467..c0b18e42d 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_root.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_root.py
@@ -257,15 +257,15 @@ class Test(TestController):
         with h.push_config(tg.config, **{'forgeblog.rate_limits': '{"3600": 0}'}):
             r = self._post()
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(wf['message'], 'Create/edit rate limit exceeded. Please try again later.')
+            assert wf['status'] == 'error'
+            assert wf['message'] == 'Create/edit rate limit exceeded. Please try again later.'
 
     def test_rate_limit_form(self):
         with h.push_config(tg.config, **{'forgeblog.rate_limits': '{"3600": 0}'}):
             r = self.app.get('/blog/new')
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(wf['message'], 'Create/edit rate limit exceeded. Please try again later.')
+            assert wf['status'] == 'error'
+            assert wf['message'] == 'Create/edit rate limit exceeded. Please try again later.'
 
     def test_admin_external_feed_invalid(self):
         r = self.app.get('/blog/')
@@ -273,7 +273,7 @@ class Test(TestController):
         form = r.forms[0]
         form['new_exfeed'].value = 'asdfasdf'
         r = form.submit()
-        assert_in('Invalid', self.webflash(r))
+        assert 'Invalid' in self.webflash(r)
 
     def test_admin_external_feed_ok(self):
         # sidebar menu doesn't expose link to this, unless "forgeblog.exfeed" config is true, but can use form anyway
@@ -282,7 +282,7 @@ class Test(TestController):
         form = r.forms[0]
         form['new_exfeed'].value = 'https://example.com/feed.rss'
         r = form.submit()
-        assert_in('External feeds updated', self.webflash(r))
+        assert 'External feeds updated' in self.webflash(r)
 
         r = self.app.get('/admin/blog/exfeed')
         r.mustcontain('https://example.com/feed.rss')
diff --git a/ForgeBlog/forgeblog/tests/test_app.py b/ForgeBlog/forgeblog/tests/test_app.py
index 98cc59fda..bb224a057 100644
--- a/ForgeBlog/forgeblog/tests/test_app.py
+++ b/ForgeBlog/forgeblog/tests/test_app.py
@@ -51,26 +51,26 @@ class TestApp:
 
     @td.with_tool('test', 'Blog', 'blog')
     def test_sitemap_xml(self):
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         BM.BlogPost.new(
             title='Blog Title',
             state='draft',
             text='This is my first blog Post',
         )
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         BM.BlogPost.new(
             title='Blog Title',
             state='published',
             text='This is my first blog Post',
             deleted=True
         )
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         BM.BlogPost.new(
             title='Blog Title',
             state='published',
             text='This is my first blog Post',
         )
-        assert_equal(1, len(c.app.sitemap_xml()))
+        assert 1 == len(c.app.sitemap_xml())
 
 
 class TestBulkExport:
@@ -107,14 +107,14 @@ class TestBulkExport:
         blog = json.loads(f.read())
         blog['posts'] = sorted(
             blog['posts'], key=lambda x: x['title'], reverse=True)
-        assert_equal(blog['posts'][0]['title'], 'Test2 title')
-        assert_equal(blog['posts'][0]['text'], 'test2 post')
-        assert_equal(blog['posts'][1]['title'], 'Test title')
-        assert_equal(blog['posts'][1]['text'], 'test post')
-        assert_equal(blog['posts'][1]['labels'],
+        assert blog['posts'][0]['title'] == 'Test2 title'
+        assert blog['posts'][0]['text'] == 'test2 post'
+        assert blog['posts'][1]['title'] == 'Test title'
+        assert blog['posts'][1]['text'] == 'test post'
+        assert (blog['posts'][1]['labels'] ==
                      ['the firstlabel', 'the second label'])
-        assert_equal(blog['posts'][1]['discussion_thread']
-                     ['posts'][0]['text'], 'test comment')
+        assert (blog['posts'][1]['discussion_thread']
+                     ['posts'][0]['text'] == 'test comment')
 
     @td.with_tool('test', 'Blog', 'blog')
     def test_export_with_attachments(self):
@@ -148,6 +148,6 @@ class TestBulkExport:
             post.discussion_thread._id,
             list(post.discussion_thread.post_class().query.find())[0].slug
         )
-        assert_equal(blog['posts'][0]['discussion_thread']['posts'][0]
-                     ['attachments'][0]['path'], file_path)
+        assert (blog['posts'][0]['discussion_thread']['posts'][0]
+                     ['attachments'][0]['path'] == file_path)
         assert os.path.exists(os.path.join(temp_dir, file_path))
\ No newline at end of file
diff --git a/ForgeBlog/forgeblog/tests/test_commands.py b/ForgeBlog/forgeblog/tests/test_commands.py
index 2e86b18ed..b1aa45196 100644
--- a/ForgeBlog/forgeblog/tests/test_commands.py
+++ b/ForgeBlog/forgeblog/tests/test_commands.py
@@ -122,14 +122,14 @@ def test_pull_rss_feeds(parsefeed):
     parsefeed.assert_called_with('http://example.com/news/feed/')
     posts = BM.BlogPost.query.find(
         {'app_config_id': tmp_app._id}).sort('timestamp', 1)
-    assert_equal(posts.count(), 4)
+    assert posts.count() == 4
     posts = posts.all()
-    assert_equal(posts[0].title, 'Test')
-    assert_equal(posts[0].text, 'This is a test [link](http://example.com/)')
-    assert_equal(posts[1].title, 'Default Title 2')
-    assert_equal(posts[1].text, 'Test feed [link](http://example.com/)')
-    assert_equal(posts[2].title, 'Default Title 3')
-    assert_equal(posts[2].text, rendered_html_content)
-    assert_equal(posts[3].title, 'Default Title 4')
-    assert_equal(posts[3].text, rendered_html_content)
+    assert posts[0].title == 'Test'
+    assert posts[0].text == 'This is a test [link](http://example.com/)'
+    assert posts[1].title == 'Default Title 2'
+    assert posts[1].text == 'Test feed [link](http://example.com/)'
+    assert posts[2].title == 'Default Title 3'
+    assert posts[2].text == rendered_html_content
+    assert posts[3].title == 'Default Title 4'
+    assert posts[3].text == rendered_html_content
 
diff --git a/ForgeBlog/forgeblog/tests/unit/test_blog_post.py b/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
index 7d5e20108..56c5e2930 100644
--- a/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
+++ b/ForgeBlog/forgeblog/tests/unit/test_blog_post.py
@@ -33,11 +33,11 @@ class TestBlogPost(BlogTestWithModel):
     def test_new(self):
         post = M.BlogPost.new(
             title='test', text='test message', state='published')
-        assert_equal(post.title, 'test')
-        assert_equal(post.text, 'test message')
-        assert_equal(post.state, 'published')
-        assert_equal(post.activity_extras['summary'], post.title)
-        assert_true('allura_id' in post.activity_extras)
+        assert post.title == 'test'
+        assert post.text == 'test message'
+        assert post.state == 'published'
+        assert post.activity_extras['summary'] == post.title
+        assert 'allura_id' in post.activity_extras
 
 
 class TestFeed(BlogTestWithModel):
@@ -57,7 +57,7 @@ class TestFeed(BlogTestWithModel):
             description=post.text,
             author=post.author(),
             pubdate=post.timestamp)
-        assert_equal(f.pubdate, datetime(2012, 10, 29, 9, 57, 21, 465000))
+        assert f.pubdate == datetime(2012, 10, 29, 9, 57, 21, 465000)
 
 
 class TestHtmlPreview(BlogTestWithModel):
@@ -77,14 +77,14 @@ class TestHtmlPreview(BlogTestWithModel):
                 "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
                 "occaecat cupidatat non proident, sunt in culpa qui officia "
                 "deserunt mollit anim id est laborum.")
-        assert_equal(self._make_post(text).html_text_preview, wrapped(text))
+        assert self._make_post(text).html_text_preview == wrapped(text)
 
     def test_single_short_paragraph(self):
         text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
                 "sed do eiusmod tempor incididunt ut labore et dolore magna "
                 "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
                 "ullamco laboris nisi ut aliquip ex ea commodo consequat.")
-        assert_equal(self._make_post(text).html_text_preview, wrapped(text))
+        assert self._make_post(text).html_text_preview == wrapped(text)
 
     def test_multi_paragraph_short(self):
         text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
@@ -100,7 +100,7 @@ class TestHtmlPreview(BlogTestWithModel):
                     '<p>Ut enim ad minim veniam, quis nostrud exercitation '
                     'ullamco laboris nisi ut aliquip ex ea commodo '
                     'consequat.</p></div>')
-        assert_equal(self._make_post(text).html_text_preview, expected)
+        assert self._make_post(text).html_text_preview == expected
 
     def test_multi_paragraph_long(self):
         text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
@@ -134,4 +134,4 @@ class TestHtmlPreview(BlogTestWithModel):
                     'anim id est laborum.... '
                     '<a class="" href="/p/test/blog/%s/%02i/untitled/">'
                     'read more</a></p></div>') % (now.year, now.month)
-        assert_equal(self._make_post(text).html_text_preview, expected)
+        assert self._make_post(text).html_text_preview == expected
diff --git a/ForgeChat/forgechat/tests/functional/test_root.py b/ForgeChat/forgechat/tests/functional/test_root.py
index 96426c140..024e3a460 100644
--- a/ForgeChat/forgechat/tests/functional/test_root.py
+++ b/ForgeChat/forgechat/tests/functional/test_root.py
@@ -39,9 +39,9 @@ class TestRootController(TestController):
         data = {'channel': 'test channel',
                 '_session_id': self.app.cookies['_session_id']}
         ch = CM.ChatChannel.query.get()
-        assert_equal(ch.channel, '')
+        assert ch.channel == ''
         resp = self.app.post('/p/test/admin/chat/configure', data)
         expected = {'status': 'ok', 'message': 'Chat options updated'}
-        assert_equal(json.loads(self.webflash(resp)), expected)
+        assert json.loads(self.webflash(resp)) == expected
         ch = CM.ChatChannel.query.get()
-        assert_equal(ch.channel, 'test channel')
+        assert ch.channel == 'test channel'
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index bc4a0373a..a20cb16e9 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -156,8 +156,8 @@ class TestForumMessageHandling(TestController):
         self.user = M.User.query.get(username='root')
 
     def test_has_access(self):
-        assert_false(c.app.has_access(M.User.anonymous(), 'testforum'))
-        assert_true(c.app.has_access(M.User.query.get(username='root'), 'testforum'))
+        assert not c.app.has_access(M.User.anonymous(), 'testforum')
+        assert c.app.has_access(M.User.query.get(username='root'), 'testforum')
 
     def test_post(self):
         self._post('testforum', 'Test Thread', 'Nothing here')
@@ -168,19 +168,19 @@ class TestForumMessageHandling(TestController):
     def test_reply(self):
         self._post('testforum', 'Test Thread', 'Nothing here',
                    message_id='test_reply@domain.net')
-        assert_equal(FM.ForumThread.query.find().count(), 1)
+        assert FM.ForumThread.query.find().count() == 1
         posts = FM.ForumPost.query.find()
-        assert_equal(posts.count(), 1)
-        assert_equal(FM.ForumThread.query.get().num_replies, 1)
-        assert_equal(FM.ForumThread.query.get().first_post_id, 'test_reply@domain.net')
+        assert posts.count() == 1
+        assert FM.ForumThread.query.get().num_replies == 1
+        assert FM.ForumThread.query.get().first_post_id == 'test_reply@domain.net'
 
         post = posts.first()
         self._post('testforum', 'Test Reply', 'Nothing here, either',
                    message_id='test_reply-msg2@domain.net',
                    in_reply_to=['test_reply@domain.net'])
-        assert_equal(FM.ForumThread.query.find().count(), 1)
-        assert_equal(FM.ForumPost.query.find().count(), 2)
-        assert_equal(FM.ForumThread.query.get().first_post_id, 'test_reply@domain.net')
+        assert FM.ForumThread.query.find().count() == 1
+        assert FM.ForumPost.query.find().count() == 2
+        assert FM.ForumThread.query.get().first_post_id == 'test_reply@domain.net'
 
     def test_reply_using_references_headers(self):
         self._post('testforum', 'Test Thread', 'Nothing here',
@@ -193,8 +193,8 @@ class TestForumMessageHandling(TestController):
                    message_id='second-message-id',
                    in_reply_to=['some-other-id@not.helpful.com'],
                    references=refs)
-        assert_equal(FM.ForumThread.query.find().count(), 1)
-        assert_equal(FM.ForumPost.query.find().count(), 2)
+        assert FM.ForumThread.query.find().count() == 1
+        assert FM.ForumPost.query.find().count() == 2
 
         prev_post = FM.ForumPost.query.find().sort('timestamp', pymongo.DESCENDING).first()
         refs = M.Notification._references(thread, prev_post) + ['second-message-id']
@@ -202,8 +202,8 @@ class TestForumMessageHandling(TestController):
                    message_id='third-message-id',
                    # missing in_reply_to altogether
                    references=refs)
-        assert_equal(FM.ForumThread.query.find().count(), 1)
-        assert_equal(FM.ForumPost.query.find().count(), 3)
+        assert FM.ForumThread.query.find().count() == 1
+        assert FM.ForumPost.query.find().count() == 3
 
     def test_attach(self):
         # runs handle_artifact_message() with filename field
@@ -367,7 +367,7 @@ class TestForum(TestController):
         form['add_forum.description'] = '<a href="http://cnn.com">This is CNN</a>'
         form.submit()
         r = self.app.get('/discussion/')
-        assert_equal(len(r.html.findAll('a', rel='nofollow')), 2)
+        assert len(r.html.findAll('a', rel='nofollow')) == 2
 
     def test_forum_search(self):
         self.app.get('/discussion/search')
@@ -459,13 +459,13 @@ class TestForum(TestController):
             params[f.find('input', {'style': 'width: 90%'})['name']] = "this is my post"
             r = self.app.post('/discussion/save_new_topic', params=params)
 
-        assert_equal(5, FM.ForumPost.query.find({'status': 'ok'}).count())
+        assert 5 == FM.ForumPost.query.find({'status': 'ok'}).count()
 
         r = self.app.post('/discussion/testforum/moderate/save_moderation_bulk_user', params={
             'username': 'test-admin',
             'spam': '1'})
-        assert_in('5 posts marked as spam', self.webflash(r))
-        assert_equal(5, FM.ForumPost.query.find({'status': 'spam'}).count())
+        assert '5 posts marked as spam' in self.webflash(r)
+        assert 5 == FM.ForumPost.query.find({'status': 'spam'}).count()
 
     def test_posting(self):
         r = self.app.get('/discussion/create_topic/')
@@ -514,7 +514,7 @@ class TestForum(TestController):
         r = self.app.post('/discussion/save_new_topic', params=params)
         n = M.Notification.query.find(
             dict(subject="[test:discussion] this is <h2> o'clock")).first()
-        assert_in('---\n\n[this is &lt;h2&gt; o&#39;clock]', n.text)
+        assert '---\n\n[this is &lt;h2&gt; o&#39;clock]' in n.text
 
     def _set_anon_allowed(self):
         r = self.app.get('/admin/discussion/permissions')
@@ -557,7 +557,7 @@ class TestForum(TestController):
         assert 'name="approve"' not in r
         assert 'name="spam"' not in r
         assert "Post content" not in r
-        assert_equal(spam_checker.check.call_args[0][0], 'Test Thread\nPost content')
+        assert spam_checker.check.call_args[0][0] == 'Test Thread\nPost content'
 
         # assert unapproved thread replies do not appear
         f = thread.html.find('div', {'class': 'comment-row reply_post_form'}).find('form')
@@ -572,7 +572,7 @@ class TestForum(TestController):
         r = self.app.get(thread.request.url,
                          extra_environ=dict(username='*anonymous'))
         assert 'anon reply to anon post' not in r
-        assert_equal(spam_checker.check.call_args[0][0], 'anon reply to anon post content')
+        assert spam_checker.check.call_args[0][0] == 'anon reply to anon post content'
 
         # assert moderation controls appear for admin
         r = self.app.get(thread.request.url)
@@ -619,8 +619,8 @@ class TestForum(TestController):
         ThreadLocalORMSession.flush_all()
         t = M.Thread()
         p = M.Post(thread=t)
-        assert_in('TestRole', [r.name for r in c.project.named_roles])
-        assert_false(t.is_spam(p))
+        assert 'TestRole' in [r.name for r in c.project.named_roles]
+        assert not t.is_spam(p)
 
     def test_thread(self):
         r = self.app.get('/discussion/create_topic/')
@@ -717,7 +717,7 @@ class TestForum(TestController):
     def check_announcement_table(self, response, topic_name):
         assert response.html.find(text='Announcements')
         rows = self.get_table_rows(response, 'announcements')
-        assert_equal(len(rows), 1)
+        assert len(rows) == 1
         cell = rows[0].findAll('td', {'class': 'topic'})
         assert topic_name in str(cell)
 
@@ -739,7 +739,7 @@ class TestForum(TestController):
             flags='Announcement',
             discussion='testforum'))
         thread2 = FM.ForumThread.query.get(_id=thread_id)
-        assert_equal(thread2.flags, ['Announcement'])
+        assert thread2.flags == ['Announcement']
 
         # Check that announcements are on front discussion page
         r = self.app.get('/discussion/')
@@ -804,7 +804,7 @@ class TestForum(TestController):
         # Check that threads are ordered in reverse creation order
         r = self.app.get('/discussion/testforum/')
         rows = self.get_table_rows(r, 'forum_threads')
-        assert_equal(len(rows), 2)
+        assert len(rows) == 2
         assert 'topic2' in str(rows[0])
         assert 'topic1' in str(rows[1])
 
@@ -813,12 +813,12 @@ class TestForum(TestController):
             flags='Sticky',
             discussion='testforum'))
         thread1 = FM.ForumThread.query.get(_id=tid1)
-        assert_equal(thread1.flags, ['Sticky'])
+        assert thread1.flags == ['Sticky']
 
         # Check that Sticky thread is at the top
         r = self.app.get('/discussion/testforum/')
         rows = self.get_table_rows(r, 'forum_threads')
-        assert_equal(len(rows), 2)
+        assert len(rows) == 2
         assert 'topic1' in rows[0].text
         assert 'topic2' in rows[1].text
 
@@ -827,14 +827,14 @@ class TestForum(TestController):
             flags='',
             discussion='testforum'))
         thread1 = FM.ForumThread.query.get(_id=tid1)
-        assert_equal(thread1.flags, [])
+        assert thread1.flags == []
 
         # Would check that threads are again in reverse creation order,
         # but so far we actually sort by mod_date, and resetting a flag
         # updates it
         r = self.app.get('/discussion/testforum/')
         rows = self.get_table_rows(r, 'forum_threads')
-        assert_equal(len(rows), 2)
+        assert len(rows) == 2
         # assert 'topic2' in str(rows[0])
         # assert 'topic1' in str(rows[1])
 
@@ -868,7 +868,7 @@ class TestForum(TestController):
         # make sure the posts are in the original thread
         posts = thread.html.find('div', {'id': 'comment'}).findAll(
             'div', {'class': 'discussion-post'})
-        assert_equal(len(posts), 2)
+        assert len(posts) == 2
         # move the thread
         r = self.app.post(url + 'moderate', params=dict(
             flags='',
@@ -876,7 +876,7 @@ class TestForum(TestController):
         # make sure all the posts got moved
         posts = r.html.find('div', {'id': 'comment'}).findAll(
             'div', {'class': 'discussion-post'})
-        assert_equal(len(posts), 2)
+        assert len(posts) == 2
 
     def test_rename_thread(self):
         # make the topic
@@ -914,11 +914,11 @@ class TestForum(TestController):
         sidebar = r.html.find('div', {'id': 'sidebar'})
         sidebar_menu = str(sidebar)
         sidebar_links = [i['href'] for i in sidebar.findAll('a')]
-        assert_in("/p/test/discussion/create_topic/", sidebar_links)
-        assert_in("/p/test/discussion/new_forum", sidebar_links)
-        assert_in('<h3 class="">Help</h3>', sidebar_menu)
-        assert_in("/nf/markdown_syntax", sidebar_links)
-        assert_not_in("flag_as_spam", sidebar_links)
+        assert "/p/test/discussion/create_topic/" in sidebar_links
+        assert "/p/test/discussion/new_forum" in sidebar_links
+        assert '<h3 class="">Help</h3>' in sidebar_menu
+        assert "/nf/markdown_syntax" in sidebar_links
+        assert "flag_as_spam" not in sidebar_links
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
@@ -931,18 +931,18 @@ class TestForum(TestController):
         params[f.find('input', {'style': 'width: 90%'})['name']] = 'AAA'
         thread = self.app.post('/discussion/save_new_topic', params=params).follow()
         thread_sidebarmenu = str(thread.html.find('div', {'id': 'sidebar'}))
-        assert_in("flag_as_spam", thread_sidebarmenu)
+        assert "flag_as_spam" in thread_sidebarmenu
 
     def test_sidebar_menu_anon(self):
         r = self.app.get('/discussion/')
         sidebar = r.html.find('div', {'id': 'sidebar'})
         sidebar_menu = str(sidebar)
         sidebar_links = [i['href'] for i in sidebar.findAll('a')]
-        assert_in("/p/test/discussion/create_topic/", sidebar_links)
-        assert_in("/p/test/discussion/new_forum", sidebar_links)
-        assert_in('<h3 class="">Help</h3>', sidebar_menu)
-        assert_in("/nf/markdown_syntax", sidebar_links)
-        assert_not_in("flag_as_spam", sidebar_menu)
+        assert "/p/test/discussion/create_topic/" in sidebar_links
+        assert "/p/test/discussion/new_forum" in sidebar_links
+        assert '<h3 class="">Help</h3>' in sidebar_menu
+        assert "/nf/markdown_syntax" in sidebar_links
+        assert "flag_as_spam" not in sidebar_menu
         r = self.app.get('/discussion/create_topic/')
         f = r.html.find('form', {'action': '/p/test/discussion/save_new_topic'})
         params = dict()
@@ -956,7 +956,7 @@ class TestForum(TestController):
         thread = self.app.post('/discussion/save_new_topic',
                                params=params).follow(extra_environ=dict(username='*anonymous'))
         thread_sidebar_menu = str(thread.html.find('div', {'id': 'sidebar'}))
-        assert_not_in("flag_as_spam", thread_sidebar_menu)
+        assert "flag_as_spam" not in thread_sidebar_menu
 
     def test_feed(self):
         for ext in ['', '.rss', '.atom']:
@@ -1006,7 +1006,7 @@ class TestForum(TestController):
         # View the thread and make sure project last_updated is not updated
         self.app.get(url)
         timestamp_after = M.Project.query.get(shortname='test').last_updated
-        assert_equal(timestamp_before, timestamp_after)
+        assert timestamp_before == timestamp_after
 
 
 class TestForumStats(TestController):
@@ -1042,7 +1042,7 @@ class TestForumStats(TestController):
         ])
         r = self.app.get(
             '/discussion/stats_data?begin=2013-01-01&end=2013-01-06')
-        assert_equal(r.json, {
+        assert r.json == {
             'begin': '2013-01-01 00:00:00',
             'end': '2013-01-06 00:00:00',
             'data': [
@@ -1053,4 +1053,4 @@ class TestForumStats(TestController):
                 [1357344000000, 2],
                 [1357430400000, 0],
             ]
-        })
+        }
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index 8a49ae218..ff7449d1e 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -109,15 +109,15 @@ class TestImportController(TestRestApiBase):  # TestController):
         return t.replace('T', ' ').replace('Z', '')
 
     def verify_ticket(self, from_api, org):
-        assert_equal(from_api['status'], org['status'])
-        assert_equal(from_api['description'], org['description'])
-        assert_equal(from_api['summary'], org['summary'])
-        assert_equal(from_api['ticket_num'], org['id'])
-        assert_equal(from_api['created_date'],
+        assert from_api['status'] == org['status']
+        assert from_api['description'] == org['description']
+        assert from_api['summary'] == org['summary']
+        assert from_api['ticket_num'] == org['id']
+        assert (from_api['created_date'] ==
                      self.time_normalize(org['date']))
-        assert_equal(from_api['mod_date'],
+        assert (from_api['mod_date'] ==
                      self.time_normalize(org['date_updated']))
-        assert_equal(from_api['custom_fields']
-                     ['_resolution'], org['resolution'])
-        assert_equal(from_api['custom_fields']['_cc'], org['cc'])
-        assert_equal(from_api['custom_fields']['_private'], org['private'])
+        assert (from_api['custom_fields']
+                     ['_resolution'] == org['resolution'])
+        assert from_api['custom_fields']['_cc'] == org['cc']
+        assert from_api['custom_fields']['_private'] == org['private']
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
index 5f42de636..b20d610a2 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -66,55 +66,55 @@ class TestRootRestController(TestDiscussionApiBase):
     def test_forum_list(self):
         forums = self.api_get('/rest/p/test/discussion/')
         forums = forums.json['forums']
-        assert_equal(len(forums), 2)
+        assert len(forums) == 2
         forums = sorted(forums, key=lambda x: x['name'])
-        assert_equal(forums[0]['name'], 'General Discussion')
-        assert_equal(
-            forums[0]['description'], 'Forum about anything you want to talk about.')
-        assert_equal(forums[0]['num_topics'], 2)
-        assert_equal(
-            forums[0]['url'], 'http://localhost/rest/p/test/discussion/general/')
-        assert_equal(forums[0]['last_post']['subject'], 'Hi guys')
-        assert_equal(forums[0]['last_post']['author'], 'test-admin')
-        assert_equal(forums[0]['last_post']['text'], 'Hi boys and girls')
-        assert_equal(forums[1]['name'], 'Say Héllo')
-        assert_equal(forums[1]['description'], 'Say héllo here')
-        assert_equal(forums[1]['num_topics'], 0)
-        assert_equal(
-            forums[1]['url'], 'http://localhost/rest/p/test/discussion/h%C3%A9llo/')
-        assert_equal(forums[1]['last_post'], None)
+        assert forums[0]['name'] == 'General Discussion'
+        assert (
+            forums[0]['description'] == 'Forum about anything you want to talk about.')
+        assert forums[0]['num_topics'] == 2
+        assert (
+            forums[0]['url'] == 'http://localhost/rest/p/test/discussion/general/')
+        assert forums[0]['last_post']['subject'] == 'Hi guys'
+        assert forums[0]['last_post']['author'] == 'test-admin'
+        assert forums[0]['last_post']['text'] == 'Hi boys and girls'
+        assert forums[1]['name'] == 'Say Héllo'
+        assert forums[1]['description'] == 'Say héllo here'
+        assert forums[1]['num_topics'] == 0
+        assert (
+            forums[1]['url'] == 'http://localhost/rest/p/test/discussion/h%C3%A9llo/')
+        assert forums[1]['last_post'] == None
 
     def test_forum(self):
         forum = self.api_get('/rest/p/test/discussion/general/')
         forum = forum.json['forum']
-        assert_equal(forum['name'], 'General Discussion')
-        assert_equal(
-            forum['description'], 'Forum about anything you want to talk about.')
+        assert forum['name'] == 'General Discussion'
+        assert (
+            forum['description'] == 'Forum about anything you want to talk about.')
         topics = forum['topics']
-        assert_equal(len(topics), 2)
-        assert_equal(topics[0]['subject'], 'Hi guys')
-        assert_equal(topics[0]['num_views'], 0)
-        assert_equal(topics[0]['num_replies'], 1)
-        assert_equal(topics[0]['last_post']['author'], 'test-admin')
-        assert_equal(topics[0]['last_post']['text'], 'Hi boys and girls')
+        assert len(topics) == 2
+        assert topics[0]['subject'] == 'Hi guys'
+        assert topics[0]['num_views'] == 0
+        assert topics[0]['num_replies'] == 1
+        assert topics[0]['last_post']['author'] == 'test-admin'
+        assert topics[0]['last_post']['text'] == 'Hi boys and girls'
         t = ForumThread.query.find({'subject': 'Hi guys'}).first()
         url = 'http://localhost/rest/p/test/discussion/general/thread/%s/' % t._id
-        assert_equal(topics[0]['url'], url)
-        assert_equal(topics[1]['subject'], 'Let\'s talk')
-        assert_equal(topics[1]['num_views'], 0)
-        assert_equal(topics[1]['num_replies'], 1)
-        assert_equal(topics[1]['last_post']['author'], 'test-admin')
-        assert_equal(topics[1]['last_post']['text'], '1st post')
+        assert topics[0]['url'] == url
+        assert topics[1]['subject'] == 'Let\'s talk'
+        assert topics[1]['num_views'] == 0
+        assert topics[1]['num_replies'] == 1
+        assert topics[1]['last_post']['author'] == 'test-admin'
+        assert topics[1]['last_post']['text'] == '1st post'
         t = ForumThread.query.find({'subject': 'Let\'s talk'}).first()
         url = 'http://localhost/rest/p/test/discussion/general/thread/%s/' % t._id
-        assert_equal(topics[1]['url'], url)
+        assert topics[1]['url'] == url
 
     def test_forum_show_ok_topics(self):
         forum = self.api_get('/rest/p/test/discussion/general/')
         forum = forum.json['forum']
-        assert_equal(forum['name'], 'General Discussion')
+        assert forum['name'] == 'General Discussion'
         topics = forum['topics']
-        assert_equal(len(topics), 2)
+        assert len(topics) == 2
         self.create_topic('general', 'Hi again', 'It should not be shown')
         t = ForumThread.query.find({'subject': 'Hi again'}).first()
         first_post = t.first_post
@@ -122,57 +122,57 @@ class TestRootRestController(TestDiscussionApiBase):
         first_post.commit()
         forum = self.api_get('/rest/p/test/discussion/general/')
         forum = forum.json['forum']
-        assert_equal(forum['name'], 'General Discussion')
+        assert forum['name'] == 'General Discussion'
         topics = forum['topics']
-        assert_equal(len(topics), 2)
+        assert len(topics) == 2
 
     def test_topic(self):
         forum = self.api_get('/rest/p/test/discussion/general/')
         forum = forum.json['forum']
-        assert_equal(forum['name'], 'General Discussion')
-        assert_equal(
-            forum['description'], 'Forum about anything you want to talk about.')
+        assert forum['name'] == 'General Discussion'
+        assert (
+            forum['description'] == 'Forum about anything you want to talk about.')
         topics = forum['topics']
         topic = self.api_get(topics[0]['url'][len('http://localhost'):])
         topic = topic.json['topic']
-        assert_equal(len(topic['posts']), 1)
-        assert_equal(topic['subject'], 'Hi guys')
-        assert_equal(topic['posts'][0]['text'], 'Hi boys and girls')
-        assert_equal(topic['posts'][0]['subject'], 'Hi guys')
-        assert_in('timestamp', topic['posts'][0])
-        assert_in('last_edited', topic['posts'][0])
+        assert len(topic['posts']) == 1
+        assert topic['subject'] == 'Hi guys'
+        assert topic['posts'][0]['text'] == 'Hi boys and girls'
+        assert topic['posts'][0]['subject'] == 'Hi guys'
+        assert 'timestamp' in topic['posts'][0]
+        assert 'last_edited' in topic['posts'][0]
 
     def test_forum_list_pagination(self):
         resp = self.app.get('/rest/p/test/discussion/?limit=1')
         forums = resp.json['forums']
-        assert_equal(len(forums), 1)
-        assert_equal(forums[0]['name'], 'General Discussion')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 0)
-        assert_equal(resp.json['limit'], 1)
+        assert len(forums) == 1
+        assert forums[0]['name'] == 'General Discussion'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 0
+        assert resp.json['limit'] == 1
         resp = self.app.get('/rest/p/test/discussion/?limit=1&page=1')
         forums = resp.json['forums']
-        assert_equal(len(forums), 1)
-        assert_equal(forums[0]['name'], 'Say Héllo')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 1)
-        assert_equal(resp.json['limit'], 1)
+        assert len(forums) == 1
+        assert forums[0]['name'] == 'Say Héllo'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 1
+        assert resp.json['limit'] == 1
 
     def test_forum_pagination(self):
         resp = self.app.get('/rest/p/test/discussion/general/?limit=1')
         topics = resp.json['forum']['topics']
-        assert_equal(len(topics), 1)
-        assert_equal(topics[0]['subject'], 'Hi guys')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 0)
-        assert_equal(resp.json['limit'], 1)
+        assert len(topics) == 1
+        assert topics[0]['subject'] == 'Hi guys'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 0
+        assert resp.json['limit'] == 1
         resp = self.app.get('/rest/p/test/discussion/general/?limit=1&page=1')
         topics = resp.json['forum']['topics']
-        assert_equal(len(topics), 1)
-        assert_equal(topics[0]['subject'], 'Let\'s talk')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 1)
-        assert_equal(resp.json['limit'], 1)
+        assert len(topics) == 1
+        assert topics[0]['subject'] == 'Let\'s talk'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 1
+        assert resp.json['limit'] == 1
 
     def test_topic_pagination(self):
         thread = ForumThread.query.find({'subject': 'Hi guys'}).first()
@@ -180,25 +180,25 @@ class TestRootRestController(TestDiscussionApiBase):
         url = '/rest/p/test/discussion/general/thread/%s/' % thread._id
         resp = self.app.get(url + '?limit=1')
         posts = resp.json['topic']['posts']
-        assert_equal(len(posts), 1)
-        assert_equal(posts[0]['text'], 'Hi boys and girls')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 0)
-        assert_equal(resp.json['limit'], 1)
+        assert len(posts) == 1
+        assert posts[0]['text'] == 'Hi boys and girls'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 0
+        assert resp.json['limit'] == 1
         resp = self.app.get(url + '?limit=1&page=1')
         posts = resp.json['topic']['posts']
-        assert_equal(len(posts), 1)
-        assert_equal(posts[0]['text'], 'I am second post')
-        assert_equal(resp.json['count'], 2)
-        assert_equal(resp.json['page'], 1)
-        assert_equal(resp.json['limit'], 1)
+        assert len(posts) == 1
+        assert posts[0]['text'] == 'I am second post'
+        assert resp.json['count'] == 2
+        assert resp.json['page'] == 1
+        assert resp.json['limit'] == 1
 
     def test_topic_show_ok_only(self):
         thread = ForumThread.query.find({'subject': 'Hi guys'}).first()
         url = '/rest/p/test/discussion/general/thread/%s/' % thread._id
         resp = self.app.get(url)
         posts = resp.json['topic']['posts']
-        assert_equal(len(posts), 1)
+        assert len(posts) == 1
         thread.post('Hello', 'I am not ok post')
         last_post = thread.last_post
         last_post.status = 'pending'
@@ -206,7 +206,7 @@ class TestRootRestController(TestDiscussionApiBase):
         ThreadLocalORMSession.flush_all()
         resp = self.app.get(url)
         posts = resp.json['topic']['posts']
-        assert_equal(len(posts), 1)
+        assert len(posts) == 1
 
     def test_security(self):
         p = M.Project.query.get(shortname='test')
@@ -240,11 +240,11 @@ class TestRootRestController(TestDiscussionApiBase):
             form['forum-1.members_only'] = True
         form.submit()
         r = self.api_get('/rest/p/test/discussion/')
-        assert_equal(len(r.json['forums']), 2)
+        assert len(r.json['forums']) == 2
         r = self.app.get('/rest/p/test/discussion/',
                          extra_environ={'username': '*anonymous'})
-        assert_equal(len(r.json['forums']), 1)
-        assert_equal(r.json['forums'][0]['shortname'], 'general')
+        assert len(r.json['forums']) == 1
+        assert r.json['forums'][0]['shortname'] == 'general'
 
     def test_has_access_no_params(self):
         self.api_get('/rest/p/test/discussion/has_access', status=404)
@@ -256,13 +256,13 @@ class TestRootRestController(TestDiscussionApiBase):
         r = self.api_get(
             '/rest/p/test/discussion/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/discussion/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -278,10 +278,10 @@ class TestRootRestController(TestDiscussionApiBase):
         r = self.api_get(
             '/rest/p/test/discussion/has_access?user=test-admin&perm=post',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/discussion/has_access?user=*anonymous&perm=admin',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
diff --git a/ForgeDiscussion/forgediscussion/tests/test_app.py b/ForgeDiscussion/forgediscussion/tests/test_app.py
index b93666e48..bb0b8d64b 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_app.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_app.py
@@ -48,7 +48,7 @@ class TestApp(TestDiscussionApiBase):  # creates some sample data
     @td.with_discussion
     def test_tickets_stats_24hr(self):
         # invoked normally via entry point
-        assert_equal(2, posts_24hr())
+        assert 2 == posts_24hr()
 
 
 class TestAppSitemap:
@@ -60,27 +60,27 @@ class TestAppSitemap:
 
     @td.with_discussion
     def test_sitemap_xml(self):
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         forum = utils.create_forum(c.app, dict(
             shortname='test-forum',
             name="Test Forum",
             description="Test Forum Description",
         ))
         ThreadLocalORMSession.flush_all()
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         thread = ForumThread(
             subject='test-thread',
         )
         thread.set_forum(forum)
         ThreadLocalORMSession.flush_all()
 
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         thread.post(
             subject='test-post',
             text='this is a test post.',
         )
         ThreadLocalORMSession.flush_all()
-        assert_equal(1, len(c.app.sitemap_xml()))
+        assert 1 == len(c.app.sitemap_xml())
 
 
 class TestBulkExport(TestDiscussionApiBase):
@@ -98,22 +98,22 @@ class TestBulkExport(TestDiscussionApiBase):
         discussion = json.loads(f.read())
         forums = sorted(discussion['forums'], key=lambda x: x['name'])
 
-        assert_equal(forums[0]['shortname'], 'general')
-        assert_equal(
-            forums[0]['description'], 'Forum about anything you want to talk about.')
-        assert_equal(forums[0]['name'], 'General Discussion')
+        assert forums[0]['shortname'] == 'general'
+        assert (
+            forums[0]['description'] == 'Forum about anything you want to talk about.')
+        assert forums[0]['name'] == 'General Discussion'
         forums[0]['threads'] = sorted(forums[0]['threads'],
                                       key=lambda x: x['posts'][0]['subject'])
-        assert_equal(
-            forums[0]['threads'][0]['posts'][0]['text'], 'Hi boys and girls')
-        assert_equal(
-            forums[0]['threads'][0]['posts'][0]['subject'], 'Hi guys')
-        assert_equal(forums[0]['threads'][1]['posts'][0]['text'], '1st post')
-        assert_equal(
-            forums[0]['threads'][1]['posts'][0]['subject'], "Let's talk")
-        assert_equal(forums[1]['shortname'], 'héllo')
-        assert_equal(forums[1]['description'], 'Say héllo here')
-        assert_equal(forums[1]['name'], 'Say Héllo')
+        assert (
+            forums[0]['threads'][0]['posts'][0]['text'] == 'Hi boys and girls')
+        assert (
+            forums[0]['threads'][0]['posts'][0]['subject'] == 'Hi guys')
+        assert forums[0]['threads'][1]['posts'][0]['text'] == '1st post'
+        assert (
+            forums[0]['threads'][1]['posts'][0]['subject'] == "Let's talk")
+        assert forums[1]['shortname'] == 'héllo'
+        assert forums[1]['description'] == 'Say héllo here'
+        assert forums[1]['name'] == 'Say Héllo'
 
     def test_export_with_attachments(self):
         project = M.Project.query.get(shortname='test')
@@ -142,5 +142,5 @@ class TestBulkExport(TestDiscussionApiBase):
             post.slug,
             'test_file'
         )
-        assert_equal(threads[0]['posts'][0]['attachments'][0]['path'], file_path)
+        assert threads[0]['posts'][0]['attachments'][0]['path'] == file_path
         os.path.exists(file_path)
diff --git a/ForgeFeedback/forgefeedback/tests/functional/test_root.py b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
index 371d491b6..37866f797 100644
--- a/ForgeFeedback/forgefeedback/tests/functional/test_root.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -38,31 +38,31 @@ class TestFeedback(TestController):
         self.app.get('/feedback/')
         r = self.app.get('/p/test/feedback')
         assert 'test' in r
-        assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>', r)
+        assert '<a href="/p/test/feedback/new_feedback">Feedback</a>' in r
 
     def test_new_feedback(self):
         c.user = M.User.by_username('test-admin')
         self.app.get('/feedback/')
         r = self.app.get('/p/test/feedback/new_feedback/')
-        assert_in('Provide your feedback for <b> Test Project</b>', r)
-        assert_in('Enter your feedback here', r)
+        assert 'Provide your feedback for <b> Test Project</b>' in r
+        assert 'Enter your feedback here' in r
 
     def test_create_feedback(self):
         resp = post_feedback(self)
         resp = resp.follow()
-        assert_in('Good tool', resp)
+        assert 'Good tool' in resp
 
     def test_edit_feedback(self):
         post_feedback(self)
         data = {'rating': '2', 'description': 'Not useful'}
         resp = self.app.post('/p/test/feedback/edit_user_review', data)
         resp = resp.follow()
-        assert_in('Not useful', resp)
+        assert 'Not useful' in resp
 
     def test_delete_feedback(self):
         post_feedback(self)
         resp = self.app.post('/p/test/feedback/delete_feedback')
-        assert_in('Success', resp)
+        assert 'Success' in resp
 
 
 def post_feedback(self):
diff --git a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
index 19d335dd9..39ba76c70 100644
--- a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -48,7 +48,7 @@ def test_role_assignments():
     def check_access(perm):
         pred = security.has_access(c.app, perm)
         return pred(user=admin), pred(user=user), pred(user=anon)
-    assert_equal(check_access('read'), (True, True, True))
-    assert_equal(check_access('create'), (True, True, False))
-    assert_equal(check_access('update'), (True, False, False))
-    assert_equal(check_access('delete'), (True, False, False))
+    assert check_access('read') == (True, True, True)
+    assert check_access('create') == (True, True, False)
+    assert check_access('update') == (True, False, False)
+    assert check_access('delete') == (True, False, False)
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
index b4996b310..a5863d3d4 100644
--- a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
@@ -29,14 +29,14 @@ class TestFeedback(FeedbackTestWithModel):
         feedback = M.Feedback()
         feedback.rating = '4'
         feedback.description = 'Very good tool'
-        assert_equal(feedback.rating, '4')
-        assert_equal(feedback.description, 'Very good tool')
-        assert_equal(feedback.activity_extras['summary'], feedback.description)
-        assert_true('allura_id' in feedback.activity_extras)
+        assert feedback.rating == '4'
+        assert feedback.description == 'Very good tool'
+        assert feedback.activity_extras['summary'] == feedback.description
+        assert 'allura_id' in feedback.activity_extras
 
     def test_index(self):
         feedback = M.Feedback()
         feedback.rating = '4'
         feedback.description = 'Good tool'
         result = feedback.index()
-        assert_equal(result["text"], 'Good tool')
+        assert result["text"] == 'Good tool'
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
index a4ac76124..d636594a8 100644
--- a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -56,7 +56,7 @@ class TestFeedbackApp(FeedbackTestWithModel):
     def test_getRating(self):
         create_feedbacks()
         rating = feedback_main.RootController().getRating()
-        assert_equal(rating, 3.5)
+        assert rating == 3.5
 
     def test_edit_feedback(self):
         create_feedbacks()
diff --git a/ForgeFiles/forgefiles/tests/functional/test_root.py b/ForgeFiles/forgefiles/tests/functional/test_root.py
index da6b6754a..999fd5367 100644
--- a/ForgeFiles/forgefiles/tests/functional/test_root.py
+++ b/ForgeFiles/forgefiles/tests/functional/test_root.py
@@ -77,7 +77,7 @@ class TestFiles(TestController):
         data1 = {'folder_id': str(folder_object._id), 'remarks': 'Publishing new Version'}
         self.app.post('/p/test/files/publish_folder', data1)
         resp = self.app.get('/files/')
-        assert_equals(folder_object.published, True)
+        assert folder_object.published == True
 
     def test_link_file(self):
         file_object = upload_file(self)
@@ -85,7 +85,7 @@ class TestFiles(TestController):
         data1 = {'file_id': str(db_file_object._id)}
         self.app.post('/p/test/files/link_file', data1)
         resp = self.app.get('/files/')
-        assert_true(str(db_file_object.linked_to_download) in resp)
+        assert str(db_file_object.linked_to_download) in resp
 
     def test_disable_folder(self):
         create_folder(self)
@@ -93,7 +93,7 @@ class TestFiles(TestController):
         data1 = {'folder_id': str(folder_object._id), 'status': 'True'}
         self.app.post('/p/test/files/disable_folder', data1)
         resp = self.app.get('/files/')
-        assert_true(str(folder_object.disabled) in resp)
+        assert str(folder_object.disabled) in resp
 
     def test_disable_file(self):
         file_object = upload_file(self)
@@ -101,7 +101,7 @@ class TestFiles(TestController):
         data1 = {'file_id': str(db_file_object._id), 'status': 'True'}
         self.app.post('/p/test/files/disable_file', data1)
         resp = self.app.get('/files/')
-        assert_true(str(db_file_object.disabled) in resp)
+        assert str(db_file_object.disabled) in resp
 
     def test_delete_folder(self):
         create_folder(self)
diff --git a/ForgeFiles/forgefiles/tests/model/test_files.py b/ForgeFiles/forgefiles/tests/model/test_files.py
index a9a6b5eb3..38929e68e 100644
--- a/ForgeFiles/forgefiles/tests/model/test_files.py
+++ b/ForgeFiles/forgefiles/tests/model/test_files.py
@@ -34,10 +34,10 @@ class TestUpload(FilesTestWithModel):
         upload_folder.published = True
         upload_folder.remark = 'Publishing new Version'
         upload_folder.disabled = False
-        assert_equal(upload_folder.folder_name, 'testFolder')
-        assert_true(upload_folder.published)
-        assert_equal(upload_folder.remark, 'Publishing new Version')
-        assert_false(upload_folder.disabled)
+        assert upload_folder.folder_name == 'testFolder'
+        assert upload_folder.published
+        assert upload_folder.remark == 'Publishing new Version'
+        assert not upload_folder.disabled
 
     def test_upload_file(self):
         '''Creates an object of the UploadFiles Collection and tests its fields'''
@@ -48,7 +48,7 @@ class TestUpload(FilesTestWithModel):
         upload_file.file_url = 'TestFolder/testFile'
         upload_file.linked_to_download = True
         upload_file.published = False
-        assert_equal(upload_file.filename, 'testFile')
-        assert_equal(upload_file.filetype, 'project_file')
-        assert_true(upload_file.linked_to_download)
-        assert_false(upload_file.published)
+        assert upload_file.filename == 'testFile'
+        assert upload_file.filetype == 'project_file'
+        assert upload_file.linked_to_download
+        assert not upload_file.published
diff --git a/ForgeFiles/forgefiles/tests/test_files_roles.py b/ForgeFiles/forgefiles/tests/test_files_roles.py
index 203f331ce..2675a3e51 100644
--- a/ForgeFiles/forgefiles/tests/test_files_roles.py
+++ b/ForgeFiles/forgefiles/tests/test_files_roles.py
@@ -47,7 +47,7 @@ def test_role_assignments():
     def check_access(perm):
         pred = security.has_access(c.app, perm)
         return pred(user=admin), pred(user=user), pred(user=anon)
-    assert_equal(check_access('read'), (True, True, True))
-    assert_equal(check_access('create'), (True, False, False))
-    assert_equal(check_access('update'), (True, False, False))
-    assert_equal(check_access('delete'), (True, False, False))
+    assert check_access('read') == (True, True, True)
+    assert check_access('create') == (True, False, False)
+    assert check_access('update') == (True, False, False)
+    assert check_access('delete') == (True, False, False)
diff --git a/ForgeGit/forgegit/tests/functional/test_auth.py b/ForgeGit/forgegit/tests/functional/test_auth.py
index c5bb1cdab..d0bacfa6d 100644
--- a/ForgeGit/forgegit/tests/functional/test_auth.py
+++ b/ForgeGit/forgegit/tests/functional/test_auth.py
@@ -86,6 +86,6 @@ class TestGitUserPermissions(TestController):
     def test_list_repos(self):
         r = self.app.get('/auth/repo_permissions',
                          params=dict(username='test-admin'), status=200)
-        assert_equal(json.loads(r.text), {"allow_write": [
+        assert json.loads(r.text) == {"allow_write": [
             '/git/test/src-git',
-        ]})
+        ]}
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index 0a966d04e..cabeb2b0c 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -109,7 +109,7 @@ class TestUIController(TestController):
                         'added', 'eee.txt',
                         'added', 'ggg.txt']
         for i, item in enumerate(sortedCommits):
-            assert_equal(actualCommit[i], ''.join(item.findAll(text=True)).strip())
+            assert actualCommit[i] == ''.join(item.findAll(text=True)).strip()
 
 
 class TestRootController(_TestCase):
@@ -156,8 +156,8 @@ class TestRootController(_TestCase):
     def test_commit_browser_data(self):
         resp = self.app.get('/src-git/commit_browser_data')
         data = json.loads(resp.text)
-        assert_equal(
-            data['built_tree']['df30427c488aeab84b2352bdf88a3b19223f9d7a'],
+        assert (
+            data['built_tree']['df30427c488aeab84b2352bdf88a3b19223f9d7a'] ==
             {'url': '/p/test/src-git/ci/df30427c488aeab84b2352bdf88a3b19223f9d7a/',
              'oid': 'df30427c488aeab84b2352bdf88a3b19223f9d7a',
              'short_id': '[df3042]',
@@ -175,7 +175,7 @@ class TestRootController(_TestCase):
         assert '<div class="markdown_content"><p>Change README</div>' in resp, resp
         assert 'tree/README?format=raw">Download</a>' not in resp
         assert 'Tree' in resp.html.findAll('td')[2].text, resp.html.findAll('td')[2].text
-        assert_in('by Rick Copeland', squish_spaces(resp.html.findAll('td')[0].text))
+        assert 'by Rick Copeland' in squish_spaces(resp.html.findAll('td')[0].text)
         resp = self.app.get('/src-git/ci/1e146e67985dcd71c74de79613719bef7bddca4a/log/?path=/README')
         assert 'View' in resp.html.findAll('td')[2].text
         assert 'Change README' in resp
@@ -230,29 +230,29 @@ class TestRootController(_TestCase):
             r = self.app.get('/src-git/feed%s' % ext)
             channel = r.xml.find('channel')
             title = channel.find('title').text
-            assert_equal(title, 'test Git changes')
+            assert title == 'test Git changes'
             description = channel.find('description').text
-            assert_equal(description,
+            assert (description ==
                          'Recent changes to Git repository in test project')
             link = channel.find('link').text
-            assert_equal(link, 'http://localhost/p/test/src-git/')
+            assert link == 'http://localhost/p/test/src-git/'
             earliest_commit = channel.findall('item')[-1]
-            assert_equal(earliest_commit.find('title').text, 'Initial commit')
+            assert earliest_commit.find('title').text == 'Initial commit'
             link = 'http://localhost/p/test/src-git/ci/9a7df788cf800241e3bb5a849c8870f2f8259d98/'
-            assert_equal(earliest_commit.find('link').text, link)
-            assert_equal(earliest_commit.find('guid').text, link)
+            assert earliest_commit.find('link').text == link
+            assert earliest_commit.find('guid').text == link
 
         # .atom has slightly different structure
         prefix = '{http://www.w3.org/2005/Atom}'
         r = self.app.get('/src-git/feed.atom')
         title = r.xml.find(prefix + 'title').text
-        assert_equal(title, 'test Git changes')
+        assert title == 'test Git changes'
         link = r.xml.find(prefix + 'link').attrib['href']
-        assert_equal(link, 'http://localhost/p/test/src-git/')
+        assert link == 'http://localhost/p/test/src-git/'
         earliest_commit = r.xml.findall(prefix + 'entry')[-1]
-        assert_equal(earliest_commit.find(prefix + 'title').text, 'Initial commit')
+        assert earliest_commit.find(prefix + 'title').text == 'Initial commit'
         link = 'http://localhost/p/test/src-git/ci/9a7df788cf800241e3bb5a849c8870f2f8259d98/'
-        assert_equal(earliest_commit.find(prefix + 'link').attrib['href'], link)
+        assert earliest_commit.find(prefix + 'link').attrib['href'] == link
 
     def test_tree(self):
         ci = self._get_ci()
@@ -288,26 +288,26 @@ class TestRootController(_TestCase):
         ci = self._get_ci(repo='/p/test/weird-chars/')
         url = ci + 'tree/' + h.urlquote('привіт.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in('Привіт!\nWhich means Hello!', resp.text)
-        assert_equal(six.ensure_text(resp.headers.get('Content-Disposition')),
+        assert 'Привіт!\nWhich means Hello!' in resp.text
+        assert (six.ensure_text(resp.headers.get('Content-Disposition')) ==
                      'attachment;filename="%D0%BF%D1%80%D0%B8%D0%B2%D1%96%D1%82.txt"')
 
         url = ci + 'tree/' + h.urlquote('with space.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in('with space', resp.text)
-        assert_equal(six.ensure_text(resp.headers.get('Content-Disposition')),
+        assert 'with space' in resp.text
+        assert (six.ensure_text(resp.headers.get('Content-Disposition')) ==
                      'attachment;filename="with%20space.txt"')
 
         url = ci + 'tree/' + h.urlquote('with%2Furlquote-literal.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in('%2F means /', resp.body.decode('utf-8'))
-        assert_equal(resp.headers.get('Content-Disposition'),
+        assert '%2F means /' in resp.body.decode('utf-8')
+        assert (resp.headers.get('Content-Disposition') ==
                      'attachment;filename="with%252Furlquote-literal.txt"')
 
         url = ci + 'tree/' + h.urlquote('with"&:specials.txt') + '?format=raw'
         resp = self.app.get(url)
-        assert_in('"&: encodes as %22%26%3A', resp.body.decode('utf-8'))
-        assert_equal(resp.headers.get('Content-Disposition'),
+        assert '"&: encodes as %22%26%3A' in resp.body.decode('utf-8')
+        assert (resp.headers.get('Content-Disposition') ==
                      'attachment;filename="with%22%26%3Aspecials.txt"')
 
     def test_file_too_large(self):
@@ -336,17 +336,17 @@ class TestRootController(_TestCase):
         ci = self._get_ci(repo='/p/test/weird-chars/')
         resp = self.app.get(h.urlquote(ci + 'tree/привіт.txt') + '?diff=407950e8fba4dbc108ffbce0128ed1085c52cfd7')
         diffhtml = str(resp.html.select_one('.diffbrowser'))
-        assert_in(textwrap.dedent('''\
+        assert (textwrap.dedent('''\
                     <span class="gd">--- a/привіт.txt</span><span class="w"></span>
                     <span class="gi">+++ b/привіт.txt</span><span class="w"></span>
                     <span class="gu">@@ -1 +1,2 @@</span><span class="w"></span>
                     <span class="w"> </span>Привіт!<span class="w"></span>
-                    <span class="gi">+Which means Hello!</span><span class="w"></span>'''),
+                    <span class="gi">+Which means Hello!</span><span class="w"></span>''') in
                   diffhtml)
 
         resp = self.app.get(h.urlquote(ci + 'tree/привіт.txt') + '?diff=407950e8fba4dbc108ffbce0128ed1085c52cfd7&diformat=sidebyside')
         diffhtml = str(resp.html.select_one('.diffbrowser'))
-        assert_in(textwrap.dedent('''\
+        assert (textwrap.dedent('''\
                     <thead>
                     <th class="lineno"></th>
                     <th>a/привіт.txt</th>
@@ -367,7 +367,7 @@ class TestRootController(_TestCase):
                     </pre></td>
                     <td class="lineno">2</td>
                     <td class="diff-add"><pre>Which means Hello!
-                    </pre></td>'''),
+                    </pre></td>''') in
                   diffhtml)
 
     def test_diff_view_mode(self):
@@ -434,31 +434,31 @@ class TestRootController(_TestCase):
         r = self.app.get(ci + 'tree/',
                          extra_environ={'username': str(user.username)})
         opts = self.subscription_options(r)
-        assert_equal(opts['subscribed'], False)
+        assert opts['subscribed'] == False
 
         # subscribe
         r = self.app.post(str(ci + 'tree/subscribe'),
                           {'subscribe': 'True'},
                           extra_environ={'username': str(user.username)})
-        assert_equal(r.json, {'status': 'ok', 'subscribed': True})
+        assert r.json == {'status': 'ok', 'subscribed': True}
         # user is subscribed
         assert M.Mailbox.subscribed(user_id=user._id)
         r = self.app.get(ci + 'tree/',
                          extra_environ={'username': str(user.username)})
         opts = self.subscription_options(r)
-        assert_equal(opts['subscribed'], True)
+        assert opts['subscribed'] == True
 
         # unsubscribe
         r = self.app.post(str(ci + 'tree/subscribe'),
                           {'unsubscribe': 'True'},
                           extra_environ={'username': str(user.username)})
-        assert_equal(r.json, {'status': 'ok', 'subscribed': False})
+        assert r.json == {'status': 'ok', 'subscribed': False}
         # user is not subscribed
         assert not M.Mailbox.subscribed(user_id=user._id)
         r = self.app.get(ci + 'tree/',
                          extra_environ={'username': str(user.username)})
         opts = self.subscription_options(r)
-        assert_equal(opts['subscribed'], False)
+        assert opts['subscribed'] == False
 
     def test_timezone(self):
         ci = self._get_ci()
@@ -501,15 +501,15 @@ class TestRootController(_TestCase):
         self.setup_testgit_index_repo()
         r = self.app.get('/p/test/testgit-index/ci/master/tree/index/')
         form = r.html.find('form', 'tarball')
-        assert_equal(form.get('action'), '/p/test/testgit-index/ci/master/tarball')
-        assert_equal(form.input.get('value'), '/index')
+        assert form.get('action') == '/p/test/testgit-index/ci/master/tarball'
+        assert form.input.get('value') == '/index'
 
     def test_default_branch(self):
-        assert_equal(c.app.default_branch_name, 'master')
+        assert c.app.default_branch_name == 'master'
         c.app.repo.set_default_branch('zz')
-        assert_equal(c.app.default_branch_name, 'zz')
+        assert c.app.default_branch_name == 'zz'
         c.app.repo.set_default_branch('master')
-        assert_equal(c.app.default_branch_name, 'master')
+        assert c.app.default_branch_name == 'master'
 
     def test_set_default_branch(self):
         r = self.app.get('/p/test/admin/src-git/set_default_branch_name')
@@ -521,41 +521,41 @@ class TestRootController(_TestCase):
         r = self.app.get('/p/test/src-git/').follow().follow()
         assert '<span class="scm-branch-label">zz</span>' in r
         # 'bad' is a file name which in zz, but not in master
-        assert_in('bad</a>', r)
+        assert 'bad</a>' in r
 
         self.app.post('/p/test/admin/src-git/set_default_branch_name',
                       params={'branch_name': 'master'})
         r = self.app.get('/p/test/src-git/').follow().follow()
-        assert_not_in('bad</a>', r)
-        assert_in('README</a>', r)
+        assert 'bad</a>' not in r
+        assert 'README</a>' in r
 
     def test_set_checkout_url(self):
         r = self.app.get('/p/test/admin/src-git/checkout_url')
         r.form['external_checkout_url'].value = 'http://foo.bar/baz'
         r.form['merge_disabled'].checked = True
         r = r.form.submit()
-        assert_equal(json.loads(self.webflash(r))['message'],
+        assert (json.loads(self.webflash(r))['message'] ==
                      "External checkout URL successfully changed. One-click merge disabled.")
         # for some reason c.app.config.options has old values still
         app_config = M.AppConfig.query.get(_id=c.app.config._id)
-        assert_equal(app_config.options['external_checkout_url'], 'http://foo.bar/baz')
-        assert_equal(app_config.options['merge_disabled'], True)
+        assert app_config.options['external_checkout_url'] == 'http://foo.bar/baz'
+        assert app_config.options['merge_disabled'] == True
 
     def test_refresh(self):
         r = self.app.get('/p/test/src-git/refresh')
-        assert_in('refresh queued', r)
-        assert_equal(1, M.MonQTask.query.find(dict(task_name='allura.tasks.repo_tasks.refresh')).count())
+        assert 'refresh queued' in r
+        assert 1 == M.MonQTask.query.find(dict(task_name='allura.tasks.repo_tasks.refresh')).count()
 
         r = self.app.get('/p/test/src-git/refresh', extra_environ={'HTTP_REFERER': '/p/test/src-git/'},
                          status=302)
-        assert_in('is being refreshed', self.webflash(r))
-        assert_equal(2, M.MonQTask.query.find(dict(task_name='allura.tasks.repo_tasks.refresh')).count())
+        assert 'is being refreshed' in self.webflash(r)
+        assert 2 == M.MonQTask.query.find(dict(task_name='allura.tasks.repo_tasks.refresh')).count()
 
 
 class TestRestController(_TestCase):
     def test_index(self):
         resp = self.app.get('/rest/p/test/src-git/', status=200)
-        assert_equal(resp.json, {
+        assert resp.json == {
             'api_url': 'http://localhost/rest/p/test/src-git/',
             'url': 'http://localhost/p/test/src-git/',
             'mount_label': 'Git',
@@ -563,7 +563,7 @@ class TestRestController(_TestCase):
             'name': 'git',
             'clone_url_file': '/srv/git/p/test/testgit',  # should be "src-git" but test data is weird?
             'commit_count': 5,
-        })
+        }
 
     def test_commits(self):
         self.app.get('/rest/p/test/src-git/commits', status=200)
@@ -588,13 +588,13 @@ class TestHasAccessAPI(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/src-git/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/src-git/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -610,13 +610,13 @@ class TestHasAccessAPI(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/src-git/has_access?user=test-admin&perm=create',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/src-git/has_access?user=test-user&perm=create',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
 
 class TestFork(_TestCase):
@@ -723,20 +723,20 @@ class TestFork(_TestCase):
 
     def test_merge_request_detail_view(self):
         r, mr_num = self._request_merge()
-        assert_in('wants to merge', r)
+        assert 'wants to merge' in r
 
         merge_instructions = r.html.findAll('textarea')[0].getText()
-        assert_in('git checkout master', merge_instructions)
-        assert_in('git fetch /srv/git/p/test2/code master', merge_instructions)
+        assert 'git checkout master' in merge_instructions
+        assert 'git fetch /srv/git/p/test2/code master' in merge_instructions
         c_id = self.forked_repo.get_heads()[0]['object_id']
-        assert_in(f'git merge {c_id}', merge_instructions)
+        assert f'git merge {c_id}' in merge_instructions
         assert_regexp_matches(str(r), r'[0-9]+ seconds? ago')
 
         merge_form = r.html.find('div', {'class': 'merge-help-text merge-ok'})
         assert merge_form
-        assert_in('Merge request has no conflicts. You can merge automatically.', merge_form.getText())
+        assert 'Merge request has no conflicts. You can merge automatically.' in merge_form.getText()
 
-        assert_not_in('Improve documentation', r)  # no details yet
+        assert 'Improve documentation' not in r  # no details yet
 
         # a task is busy/ready to compute
         r = self.app.get('/p/test/src-git/merge-requests/1/commits_html', status=202)  # 202 used for "busy"
@@ -746,16 +746,16 @@ class TestFork(_TestCase):
         ThreadLocalORMSession.close_all()  # close ming connections so that new data gets loaded later
 
         def assert_commit_details(r):
-            assert_in('Improve documentation', r.text)
+            assert 'Improve documentation' in r.text
             revs = r.html.findAll('tr', attrs={'class': 'rev'})
-            assert_equal(len(revs), 1)
+            assert len(revs) == 1
             rev_links = revs[0].findAll('a', attrs={'class': 'rev'})
             browse_links = revs[0].findAll('a', attrs={'class': 'browse'})
-            assert_equal(rev_links[0].get('href'), '/p/test2/code/ci/%s/' % c_id)
-            assert_equal(rev_links[0].getText(), '[%s]' % c_id[:6])
-            assert_equal(browse_links[0].get('href'),
+            assert rev_links[0].get('href') == '/p/test2/code/ci/%s/' % c_id
+            assert rev_links[0].getText() == '[%s]' % c_id[:6]
+            assert (browse_links[0].get('href') ==
                          '/p/test2/code/ci/%s/tree' % c_id)
-            assert_equal(browse_links[0].getText().strip(), 'Tree')
+            assert browse_links[0].getText().strip() == 'Tree'
 
         r = self.app.get('/p/test/src-git/merge-requests/1/commits_html', status=200)
         assert_commit_details(r)
@@ -764,16 +764,16 @@ class TestFork(_TestCase):
         assert_commit_details(r)
 
         r = self.app.get('/p/test/src-git/merge-requests/1/can_merge_task_status')
-        assert_equal(r.json, {'status': 'ready'})
+        assert r.json == {'status': 'ready'}
         r = self.app.get('/p/test/src-git/merge-requests/1/can_merge_result')
-        assert_equal(r.json, {'can_merge': None})
+        assert r.json == {'can_merge': None}
         r = self.app.get('/p/test/src-git/merge-requests/1/merge_task_status')
-        assert_equal(r.json, {'status': None})
+        assert r.json == {'status': None}
 
     def test_merge_request_detail_noslash(self):
         self._request_merge()
         r = self.app.get('/p/test/src-git/merge-requests/1', status=301)
-        assert_equal(r.location, 'http://localhost/p/test/src-git/merge-requests/1/')
+        assert r.location == 'http://localhost/p/test/src-git/merge-requests/1/'
 
     def test_merge_request_with_deleted_repo(self):
         self._request_merge()
@@ -811,19 +811,19 @@ class TestFork(_TestCase):
     def test_merge_request_default_branches(self):
         _select_val = lambda r, n: r.html.find('select', {'name': n}).find(selected=True).string
         r = self.app.get('/p/test2/code/request_merge')
-        assert_equal(_select_val(r, 'source_branch'), 'master')
-        assert_equal(_select_val(r, 'target_branch'), 'master')
+        assert _select_val(r, 'source_branch') == 'master'
+        assert _select_val(r, 'target_branch') == 'master'
         r = self.app.get('/p/test2/code/ci/zz/tree/').click('Request Merge')
-        assert_equal(_select_val(r, 'source_branch'), 'zz')
-        assert_equal(_select_val(r, 'target_branch'), 'master')
+        assert _select_val(r, 'source_branch') == 'zz'
+        assert _select_val(r, 'target_branch') == 'master'
         GM.Repository.query.get(_id=c.app.repo._id).default_branch_name = 'zz'
         ThreadLocalORMSession.flush_all()
         r = self.app.get('/p/test2/code/request_merge')
-        assert_equal(_select_val(r, 'source_branch'), 'master')
-        assert_equal(_select_val(r, 'target_branch'), 'zz')
+        assert _select_val(r, 'source_branch') == 'master'
+        assert _select_val(r, 'target_branch') == 'zz'
         r = self.app.get('/p/test2/code/ci/zz/tree/').click('Request Merge')
-        assert_equal(_select_val(r, 'source_branch'), 'zz')
-        assert_equal(_select_val(r, 'target_branch'), 'zz')
+        assert _select_val(r, 'source_branch') == 'zz'
+        assert _select_val(r, 'target_branch') == 'zz'
 
     def test_merge_request_with_branch(self):
         def get_mr_page(r):
@@ -955,7 +955,7 @@ class TestFork(_TestCase):
         mr_commits.side_effect = Exception
         r = self.app.get('/p/test/src-git/merge-requests/%s/' % mr_num)
         # errors don't show up on the page directly any more, so just assert that the bg task is there
-        assert_in('commits-loading', r)
+        assert 'commits-loading' in r
         self.app.get('/p/test/src-git/merge-requests/%s/commits_html' % mr_num, status=202)  # 202 used for "busy"
 
     def test_merge_request_validation_error(self):
@@ -1042,9 +1042,9 @@ class TestGitRename(TestController):
 
         # the diff portion of the output
         resp_no_ws = re.sub(r'\s+', '', str(resp))
-        assert_in('<a href="/p/test/src-git/ci/fbb0644603bb6ecee3ebb62efe8c86efc9b84ee6/tree/f.txt" rel="nofollow">f.txt</a>'
+        assert ('<a href="/p/test/src-git/ci/fbb0644603bb6ecee3ebb62efe8c86efc9b84ee6/tree/f.txt" rel="nofollow">f.txt</a>'
                   'to<a href="/p/test/src-git/ci/b120505a61225e6c14bee3e5b5862db81628c35c/tree/f2.txt" rel="nofollow">f2.txt</a>'
-                  .replace(' ', ''), resp_no_ws)
+                  .replace(' ', '') in resp_no_ws)
         assert '<span class="empty-diff">File was renamed.</span>' in resp
 
     def test_directory_changed_type(self):
@@ -1052,11 +1052,11 @@ class TestGitRename(TestController):
         resp = self.app.get('/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/')
 
         resp_no_ws = re.sub(r'\s+', '', str(resp))
-        assert_in('<a href="/p/test/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/tree/b_dir" rel="nofollow">b_dir</a>'
+        assert ('<a href="/p/test/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/tree/b_dir" rel="nofollow">b_dir</a>'
                   '</h6>'
                   '<div id="diff-3" class="inline-diff-body">'
                   '<span class="empty-diff">Symlink.</span>'
-                  .replace(' ', ''), resp_no_ws)
+                  .replace(' ', '') in resp_no_ws)
 
     def test_symlink_in_tree(self):
         # change a_dir to a file; b_dir to a symlink
@@ -1085,7 +1085,7 @@ class TestGitBranch(TestController):
     def test_exotic_default_branch(self):
         r = self.app.get('/src-git/').follow().follow()
         assert 'README</a>' in r
-        assert_equal(c.app.repo.get_default_branch('master'), 'test')
+        assert c.app.repo.get_default_branch('master') == 'test'
 
     def test_branch_with_slashes(self):
         branches_page = self.app.get('/src-git/ref/master/branches/')
@@ -1126,19 +1126,19 @@ class TestIncludeMacro(_TestCase):
         setup_global_objects()
 
     def test_parse_repo(self):
-        assert_equal(macro.parse_repo('app'), None)
-        assert_equal(macro.parse_repo('proj:app'), None)
-        assert_equal(macro.parse_repo('nbhd:test:src-git'), None)
-        assert_equal(macro.parse_repo('a:b:c:d:e:f'), None)
-        assert_not_equal(macro.parse_repo('src-git'), None)
-        assert_not_equal(macro.parse_repo('test:src-git'), None)
-        assert_not_equal(macro.parse_repo('p:test:src-git'), None)
+        assert macro.parse_repo('app') == None
+        assert macro.parse_repo('proj:app') == None
+        assert macro.parse_repo('nbhd:test:src-git') == None
+        assert macro.parse_repo('a:b:c:d:e:f') == None
+        assert macro.parse_repo('src-git') != None
+        assert macro.parse_repo('test:src-git') != None
+        assert macro.parse_repo('p:test:src-git') != None
 
     def test_include_file_no_repo(self):
         expected = '[[include repo %s (not found)]]'
-        assert_equal(macro.include_file(None), expected % None)
-        assert_equal(macro.include_file('a:b'), expected % 'a:b')
-        assert_equal(macro.include_file('repo'), expected % 'repo')
+        assert macro.include_file(None) == expected % None
+        assert macro.include_file('a:b') == expected % 'a:b'
+        assert macro.include_file('repo') == expected % 'repo'
 
     def test_include_file_permissions(self):
         h.set_context('test', 'src-git', neighborhood='Projects')
@@ -1149,13 +1149,13 @@ class TestIncludeMacro(_TestCase):
             acl.remove(read_perm)
         c.user = M.User.anonymous()
         expected = "[[include: you don't have a read permission for repo src-git]]"
-        assert_equal(macro.include_file('src-git'), expected)
+        assert macro.include_file('src-git') == expected
 
     def test_include_file_cant_find_file(self):
         expected = "[[include can't find file %s in revision %s]]"
-        assert_equal(macro.include_file('src-git', 'a.txt'),
+        assert (macro.include_file('src-git', 'a.txt') ==
                      expected % ('a.txt', '1e146e67985dcd71c74de79613719bef7bddca4a'))
-        assert_equal(macro.include_file('src-git', 'a.txt', '6a45885ae7347f1cac5103b0050cc1be6a1496c8'),
+        assert (macro.include_file('src-git', 'a.txt', '6a45885ae7347f1cac5103b0050cc1be6a1496c8') ==
                      expected % ('a.txt', '6a45885ae7347f1cac5103b0050cc1be6a1496c8'))
 
     @patch('allura.model.repo.Blob.has_pypeline_view', new_callable=PropertyMock)
@@ -1164,9 +1164,9 @@ class TestIncludeMacro(_TestCase):
         has_html_view.return_value = False
         has_pypeline_view.return_value = False
         expected = "[[include can't display file README in revision 1e146e67985dcd71c74de79613719bef7bddca4a]]"
-        assert_equal(macro.include_file('src-git', 'README'), expected)
+        assert macro.include_file('src-git', 'README') == expected
 
     def test_include_file_display(self):
         result = macro.include_file('src-git', 'README')
-        assert_in('This is readme', result)
-        assert_in('Another Line', result)
+        assert 'This is readme' in result
+        assert 'Another Line' in result
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 9fb886289..bb687b91b 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -85,8 +85,8 @@ class TestNewGit(unittest.TestCase):
         c.lcid_cache = {}
         self.rev.tree.ls()
         # print self.rev.tree.readme()
-        assert_equal(self.rev.tree.readme(), (
-            'README', 'This is readme\nAnother Line\n'))
+        assert self.rev.tree.readme() == (
+            'README', 'This is readme\nAnother Line\n')
         assert self.rev.tree.path() == '/'
         assert self.rev.tree.url() == (
             '/p/test/src-git/ci/'
@@ -109,17 +109,17 @@ class TestNewGit(unittest.TestCase):
                 '/p/test/src-git/ci/'
                 '1e146e67985dcd71c74de79613719bef7bddca4a/')
 
-        assert_equal(self.rev.authored_user, None)
-        assert_equal(self.rev.committed_user, None)
+        assert self.rev.authored_user == None
+        assert self.rev.committed_user == None
         user = M.User.upsert('rick')
         email = user.claim_address('rcopeland@geek.net')
         email.confirmed = True
         session(email).flush(email)
         rev = self.repo.commit(self.rev._id)  # to update cached values of LazyProperty
-        assert_equal(rev.authored_user, user)
-        assert_equal(rev.committed_user, user)
-        assert_equal(
-            sorted(rev.webhook_info.keys()),
+        assert rev.authored_user == user
+        assert rev.committed_user == user
+        assert (
+            sorted(rev.webhook_info.keys()) ==
             sorted(['id', 'url', 'timestamp', 'message', 'author',
                     'committer', 'added', 'removed', 'renamed', 'modified', 'copied']))
 
@@ -257,15 +257,15 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
 
     def test_log_id_only(self):
         entries = list(self.repo.log(id_only=True))
-        assert_equal(entries, [
+        assert entries == [
             '1e146e67985dcd71c74de79613719bef7bddca4a',
             'df30427c488aeab84b2352bdf88a3b19223f9d7a',
             '6a45885ae7347f1cac5103b0050cc1be6a1496c8',
-            '9a7df788cf800241e3bb5a849c8870f2f8259d98'])
+            '9a7df788cf800241e3bb5a849c8870f2f8259d98']
 
     def test_log(self):
         entries = list(self.repo.log(id_only=False))
-        assert_equal(entries, [
+        assert entries == [
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
                           'email': 'rcopeland@geek.net',
                           'name': 'Rick Copeland'},
@@ -314,15 +314,15 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
              'refs': [],
              'size': None,
              'rename_details': {}},
-        ])
+        ]
 
     def test_log_unicode(self):
         entries = list(self.repo.log(path='völundr', id_only=False))
-        assert_equal(entries, [])
+        assert entries == []
 
     def test_log_file(self):
         entries = list(self.repo.log(path='README', id_only=False))
-        assert_equal(entries, [
+        assert entries == [
             {'authored': {'date': datetime.datetime(2010, 10, 7, 18, 44, 11),
                           'email': 'rcopeland@geek.net',
                           'name': 'Rick Copeland'},
@@ -347,7 +347,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
              'refs': [],
              'size': 15,
              'rename_details': {}},
-        ])
+        ]
 
     def test_commit(self):
         entry = self.repo.commit('HEAD')
@@ -379,13 +379,13 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         domain = '.'.join(reversed(c.app.url[1:-1].split('/'))).replace('_', '-')
         common_suffix = tg.config['forgemail.domain']
         email = f'noreply@{domain}{common_suffix}'
-        assert_in(email, notification['reply_to_address'])
+        assert email in notification['reply_to_address']
 
         commit1_loc = notification.text.find('Initial commit')
         assert commit1_loc != -1
         commit2_loc = notification.text.find('Remove file')
         assert commit2_loc != -1
-        assert_less(commit1_loc, commit2_loc)
+        assert commit1_loc < commit2_loc
 
     def test_notification_email(self):
         send_notifications(
@@ -394,7 +394,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
 
         n = M.Notification.query.find({'subject': '[test:src-git] New commit [1e146e] by Rick Copeland'}).first()
         assert n
-        assert_in('Change README', n.text)
+        assert 'Change README' in n.text
 
     def test_notification_email_multiple_commits(self):
         send_notifications(self.repo, ['df30427c488aeab84b2352bdf88a3b19223f9d7a',
@@ -458,7 +458,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
             .get_payload(decode=True).decode('utf-8')
 
         # no extra HTML in commit messages
-        assert_in('''-----
+        assert '''-----
 
 Add foo.txt.  Commit ref [616d24f8dd4e95cadd8e93df5061f09855d1a066] *bold* <b>bold</b>
 
@@ -468,20 +468,20 @@ Add foo.txt.  Commit ref [616d24f8dd4e95cadd8e93df5061f09855d1a066] *bold* <b>bo
 
 http://example.com/
 
-By Dave Brondsema''', text_body)
+By Dave Brondsema''' in text_body
         # these bracketed links could look like HTML tags, ensure they don't get removed
-        assert_in('further messages, please visit <http://localhost/auth/subscriptions/>', text_body)
+        assert 'further messages, please visit <http://localhost/auth/subscriptions/>' in text_body
 
         # limited markdown handling of commit messages (see `markdown_commit`)
         # and HTML escaped
-        assert_in('''<hr/>
+        assert '''<hr/>
 <div class="markdown_content"><p>Add foo.txt.  Commit ref <a class="alink" href="http://localhost/p/test/weird-chars/ci/616d24f8dd4e95cadd8e93df5061f09855d1a066/">[616d24f8dd4e95cadd8e93df5061f09855d1a066]</a> *bold* &lt;b&gt;bold&lt;/b&gt;</p>
 <p>* one<br/>
 * two<br/>
 * three</p>
 <p>http://example.com/</p></div>
 
-<p>By Dave Brondsema''', html_body)
+<p>By Dave Brondsema''' in html_body
 
     def test_commit_artifact_references(self):
         self._setup_weird_chars_repo()
@@ -500,9 +500,9 @@ By Dave Brondsema''', text_body)
         if os.path.isfile(os.path.join(tmpdir, "git/t/te/test/testgit.git/test-src-git-HEAD.zip")):
             os.remove(
                 os.path.join(tmpdir, "git/t/te/test/testgit.git/test-src-git-HEAD.zip"))
-        assert_equal(self.repo.tarball_path,
+        assert (self.repo.tarball_path ==
                      os.path.join(tmpdir, 'git/t/te/test/testgit.git'))
-        assert_equal(self.repo.tarball_url('HEAD'),
+        assert (self.repo.tarball_url('HEAD') ==
                      'file:///git/t/te/test/testgit.git/test-src-git-HEAD.zip')
         self.repo.tarball('HEAD')
         assert os.path.isfile(
@@ -556,20 +556,20 @@ By Dave Brondsema''', text_body)
             os.removedirs(
                 os.path.join(tmpdir, "git/t/te/test/testgit.git/test-src-git-HEAD/"))
         self.repo.tarball('HEAD')
-        assert_equal(self.repo.get_tarball_status('HEAD'), 'complete')
+        assert self.repo.get_tarball_status('HEAD') == 'complete'
 
         os.remove(
             os.path.join(tmpdir, "git/t/te/test/testgit.git/test-src-git-HEAD.zip"))
-        assert_equal(self.repo.get_tarball_status('HEAD'), None)
+        assert self.repo.get_tarball_status('HEAD') == None
 
     def test_tarball_status_task(self):
-        assert_equal(self.repo.get_tarball_status('HEAD'), None)
+        assert self.repo.get_tarball_status('HEAD') == None
 
         # create tarball task in MonQTask and check get_tarball_status
         tarball.post('HEAD', '')
 
         # task created
-        assert_equal(self.repo.get_tarball_status('HEAD'), 'ready')
+        assert self.repo.get_tarball_status('HEAD') == 'ready'
 
         task = M.MonQTask.query.get(**{
             'task_name': 'allura.tasks.repo_tasks.tarball',
@@ -580,12 +580,12 @@ By Dave Brondsema''', text_body)
         # task is running
         task.state = 'busy'
         task.query.session.flush_all()
-        assert_equal(self.repo.get_tarball_status('HEAD'), 'busy')
+        assert self.repo.get_tarball_status('HEAD') == 'busy'
 
         # when state is complete, but file don't exists, then status is None
         task.state = 'complete'
         task.query.session.flush_all()
-        assert_equal(self.repo.get_tarball_status('HEAD'), None)
+        assert self.repo.get_tarball_status('HEAD') == None
 
     def test_is_empty(self):
         assert not self.repo.is_empty()
@@ -604,13 +604,13 @@ By Dave Brondsema''', text_body)
 
     def test_default_branch_set(self):
         self.repo.default_branch_name = 'zz'
-        assert_equal(self.repo.get_default_branch('master'), 'zz')
+        assert self.repo.get_default_branch('master') == 'zz'
 
     def test_default_branch_non_standard_unset(self):
         with mock.patch.object(self.repo, 'get_branches') as gb,\
              mock.patch.object(self.repo, 'set_default_branch') as set_db:
             gb.return_value = [Object(name='foo')]
-            assert_equal(self.repo.get_default_branch('master'), 'foo')
+            assert self.repo.get_default_branch('master') == 'foo'
             set_db.assert_called_once_with('foo')
 
     def test_default_branch_non_standard_invalid(self):
@@ -618,7 +618,7 @@ By Dave Brondsema''', text_body)
              mock.patch.object(self.repo, 'set_default_branch') as set_db:
             self.repo.default_branch_name = 'zz'
             gb.return_value = [Object(name='foo')]
-            assert_equal(self.repo.get_default_branch('master'), 'foo')
+            assert self.repo.get_default_branch('master') == 'foo'
             set_db.assert_called_once_with('foo')
 
     def test_default_branch_invalid(self):
@@ -626,28 +626,28 @@ By Dave Brondsema''', text_body)
              mock.patch.object(self.repo, 'set_default_branch') as set_db:
             self.repo.default_branch_name = 'zz'
             gb.return_value = [Object(name='foo'), Object(name='master')]
-            assert_equal(self.repo.get_default_branch('master'), 'master')
+            assert self.repo.get_default_branch('master') == 'master'
             set_db.assert_called_once_with('master')
 
     def test_default_branch_no_clobber(self):
         with mock.patch.object(self.repo, 'get_branches') as gb:
             gb.return_value = []
             self.repo.default_branch_name = 'zz'
-            assert_equal(self.repo.get_default_branch('master'), 'zz')
+            assert self.repo.get_default_branch('master') == 'zz'
 
     def test_default_branch_clobber_none(self):
         with mock.patch.object(self.repo, 'get_branches') as gb:
             gb.return_value = []
             self.repo.default_branch_name = None
-            assert_equal(self.repo.get_default_branch('master'), 'master')
+            assert self.repo.get_default_branch('master') == 'master'
 
     def test_clone_url(self):
-        assert_equal(
-            self.repo.clone_url('file', 'nobody'),
+        assert (
+            self.repo.clone_url('file', 'nobody') ==
             '/srv/git/p/test/testgit')
         with h.push_config(self.repo.app.config.options, external_checkout_url='https://$username@foo.com/'):
-            assert_equal(
-                self.repo.clone_url('https', 'user'),
+            assert (
+                self.repo.clone_url('https', 'user') ==
                 'https://user@foo.com/')
 
     def test_webhook_payload(self):
@@ -707,7 +707,7 @@ By Dave Brondsema''', text_body)
                 'url': 'http://localhost/p/test/src-git/',
             },
         }
-        assert_equals(payload, expected_payload)
+        assert payload == expected_payload
 
     def test_can_merge(self):
         mr = mock.Mock(downstream_repo=Object(full_fs_path='downstream-url'),
@@ -717,7 +717,7 @@ By Dave Brondsema''', text_body)
         git = mock.Mock()
         git.merge_tree.return_value = 'clean merge'
         self.repo._impl._git.git = git
-        assert_equal(self.repo.can_merge(mr), True)
+        assert self.repo.can_merge(mr) == True
         git.fetch.assert_called_once_with('downstream-url', 'source-branch')
         git.merge_base.assert_called_once_with('cid', 'target-branch')
         git.merge_tree.assert_called_once_with(
@@ -725,7 +725,7 @@ By Dave Brondsema''', text_body)
             'target-branch',
             'cid')
         git.merge_tree.return_value = '+<<<<<<<'
-        assert_equal(self.repo.can_merge(mr), False)
+        assert self.repo.can_merge(mr) == False
 
     @mock.patch('forgegit.model.git_repo.tempfile', autospec=True)
     @mock.patch('forgegit.model.git_repo.git', autospec=True)
@@ -748,13 +748,13 @@ By Dave Brondsema''', text_body)
             bare=False,
             shared=True)
         tmp_repo = GitImplementation.return_value._git
-        assert_equal(
-            tmp_repo.git.fetch.call_args_list,
+        assert (
+            tmp_repo.git.fetch.call_args_list ==
             [mock.call('origin', 'target-branch'),
              mock.call('downstream-url', 'source-branch')])
         tmp_repo.git.checkout.assert_called_once_with('target-branch')
-        assert_equal(
-            tmp_repo.git.config.call_args_list,
+        assert (
+            tmp_repo.git.config.call_args_list ==
             [mock.call('user.name', b'Test Admin'),
              mock.call('user.email', 'allura@localhost')])
         msg = 'Merge downstream-repo-url branch source-branch into target-branch'
@@ -802,7 +802,7 @@ By Dave Brondsema''', text_body)
             'copied': [],
             'total': 2,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         diffs = repo.paged_diffs('f3de6a0e7601cdde326054a1cc708afdc1dbe70b')
         expected = {
@@ -813,7 +813,7 @@ By Dave Brondsema''', text_body)
             'changed': ['привіт.txt'],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         # initial commit is special, but must work too
         diffs = repo.paged_diffs('afaa6d93eb5661fb04f8e10e9ba1039b7441a6c7')
@@ -825,7 +825,7 @@ By Dave Brondsema''', text_body)
             'renamed': [],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         # pagination
         diffs = repo.paged_diffs('407950e8fba4dbc108ffbce0128ed1085c52cfd7', start=0, end=1)
@@ -837,7 +837,7 @@ By Dave Brondsema''', text_body)
             'changed': [],
             'total': 2,  # there are two total changes but result is limited to first
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
         diffs = repo.paged_diffs('407950e8fba4dbc108ffbce0128ed1085c52cfd7', start=1, end=2)
         expected = {
             'added': ['привіт.txt'],
@@ -847,7 +847,7 @@ By Dave Brondsema''', text_body)
             'changed': [],
             'total': 2,  # there are two total changes but result is limited to second
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
         diffs = repo.paged_diffs('346c52c1dddc729e2c2711f809336401f0ff925e')  # Test copy
         expected = {
             'added': ['README.copy'],
@@ -857,7 +857,7 @@ By Dave Brondsema''', text_body)
             'changed': ['README'],
             'total': 2,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
         diffs = repo.paged_diffs('3cb2bbcd7997f89060a14fe8b1a363f01883087f')  # Test rename
         expected = {
             'added': ['README'],
@@ -867,7 +867,7 @@ By Dave Brondsema''', text_body)
             'changed': [],
             'total': 2,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
         diffs = repo.paged_diffs('616d24f8dd4e95cadd8e93df5061f09855d1a066')  # Test type change
         expected = {
             'added': [],
@@ -877,7 +877,7 @@ By Dave Brondsema''', text_body)
             'changed': ['README.copy'],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
     @mock.patch.dict('allura.lib.app_globals.config',  {'scm.commit.git.detect_copies': 'true'})
     @td.with_tool('test', 'Git', 'src-weird', 'Git', type='git')
@@ -905,7 +905,7 @@ By Dave Brondsema''', text_body)
             'changed': ['README'],
             'total': 2,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
         diffs = repo.paged_diffs('3cb2bbcd7997f89060a14fe8b1a363f01883087f')  # Test rename
         expected = {
             'added': [],
@@ -915,11 +915,11 @@ By Dave Brondsema''', text_body)
             'changed': [],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
     def test_merge_base(self):
         res = self.repo._impl.merge_base(self.merge_request)
-        assert_equal(res, '1e146e67985dcd71c74de79613719bef7bddca4a')
+        assert res == '1e146e67985dcd71c74de79613719bef7bddca4a'
 
     def test_merge_request_commits(self):
         res = self.repo.merge_request_commits(self.merge_request)
@@ -938,7 +938,7 @@ By Dave Brondsema''', text_body)
              'refs': ['zz'],
              'rename_details': {},
              'size': None}]
-        assert_equals(res, expected)
+        assert res == expected
 
     def test_merge_request_commits_tmp_dir(self):
         """
@@ -950,19 +950,19 @@ By Dave Brondsema''', text_body)
         opt = {'scm.merge_list.git.use_tmp_dir': True}
         with h.push_config(tg.config, **opt):
             res_with_tmp = self.repo.merge_request_commits(mr)
-        assert_equals(res_without_tmp, res_with_tmp)
+        assert res_without_tmp == res_with_tmp
 
     def test_cached_branches(self):
         with mock.patch.dict('allura.lib.app_globals.config', {'repo_refs_cache_threshold': '0'}):
             rev = GM.Repository.query.get(_id=self.repo['_id'])
             branches = rev._impl._get_refs('branches')
-            assert_equal(rev.cached_branches, branches)
+            assert rev.cached_branches == branches
 
     def test_cached_tags(self):
         with mock.patch.dict('allura.lib.app_globals.config', {'repo_refs_cache_threshold': '0'}):
             rev = GM.Repository.query.get(_id=self.repo['_id'])
             tags = rev._impl._get_refs('tags')
-            assert_equal(rev.cached_tags, tags)
+            assert rev.cached_tags == tags
 
 
 class TestGitImplementation(unittest.TestCase):
@@ -1069,35 +1069,35 @@ class TestGitCommit(unittest.TestCase):
     def test_log(self):
         # path only
         commits = list(self.repo.log(id_only=True))
-        assert_equal(commits, [
+        assert commits == [
             "1e146e67985dcd71c74de79613719bef7bddca4a",
             "df30427c488aeab84b2352bdf88a3b19223f9d7a",
             "6a45885ae7347f1cac5103b0050cc1be6a1496c8",
             "9a7df788cf800241e3bb5a849c8870f2f8259d98",
-        ])
+        ]
         commits = list(self.repo.log(self.repo.head, 'README', id_only=True))
-        assert_equal(commits, [
+        assert commits == [
             "1e146e67985dcd71c74de79613719bef7bddca4a",
             "df30427c488aeab84b2352bdf88a3b19223f9d7a",
-        ])
+        ]
         commits = list(
             self.repo.log("df30427c488aeab84b2352bdf88a3b19223f9d7a", 'README', id_only=True))
-        assert_equal(commits, [
+        assert commits == [
             "df30427c488aeab84b2352bdf88a3b19223f9d7a",
-        ])
+        ]
         commits = list(self.repo.log(self.repo.head, '/a/b/c/', id_only=True))
-        assert_equal(commits, [
+        assert commits == [
             "6a45885ae7347f1cac5103b0050cc1be6a1496c8",
             "9a7df788cf800241e3bb5a849c8870f2f8259d98",
-        ])
+        ]
         commits = list(
             self.repo.log("9a7df788cf800241e3bb5a849c8870f2f8259d98", '/a/b/c/', id_only=True))
-        assert_equal(commits, [
+        assert commits == [
             "9a7df788cf800241e3bb5a849c8870f2f8259d98",
-        ])
+        ]
         commits = list(
             self.repo.log(self.repo.head, '/does/not/exist/', id_only=True))
-        assert_equal(commits, [])
+        assert commits == []
 
 
 class TestGitHtmlView(unittest.TestCase):
diff --git a/ForgeGit/forgegit/tests/test_git_app.py b/ForgeGit/forgegit/tests/test_git_app.py
index 80372039f..823004c40 100644
--- a/ForgeGit/forgegit/tests/test_git_app.py
+++ b/ForgeGit/forgegit/tests/test_git_app.py
@@ -40,7 +40,7 @@ class TestGitApp(unittest.TestCase):
         ThreadLocalORMSession.close_all()
 
     def test_admin_menu(self):
-        assert_equals(len(c.app.admin_menu()), 7)
+        assert len(c.app.admin_menu()) == 7
 
     def test_uninstall(self):
         from allura import model as M
diff --git a/ForgeImporters/forgeimporters/github/tests/test_utils.py b/ForgeImporters/forgeimporters/github/tests/test_utils.py
index 1ea4c761b..5e47bcefe 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_utils.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_utils.py
@@ -28,67 +28,67 @@ class TestGitHubMarkdownConverter:
     def test_convert_sha(self):
         text = '16c999e8c71134401a78d4d46435517b2271d6ac'
         result = self.conv.convert(text)
-        assert_equal(result, '[16c999]')
+        assert result == '[16c999]'
 
         text = 'some context  16c999e8c71134401a78d4d46435517b2271d6ac '
         result = self.conv.convert(text)
-        assert_equal(result, 'some context  [16c999] ')
+        assert result == 'some context  [16c999] '
 
     def test_convert_user_sha(self):
         text = 'user@16c999e8c71134401a78d4d46435517b2271d6ac'
         result = self.conv.convert(text)
-        assert_equal(result, '[16c999]')
+        assert result == '[16c999]'
 
         # Not an owner of current project
         text = 'another-user@16c999e8c71134401a78d4d46435517b2271d6ac'
         result = self.conv.convert(text)
-        assert_equal(result, text)
+        assert result == text
 
     def test_convert_user_repo_sha(self):
         text = 'user/project@16c999e8c71134401a78d4d46435517b2271d6ac'
         result = self.conv.convert(text)
-        assert_equal(result, '[16c999]')
+        assert result == '[16c999]'
 
         # Not a current project
         text = 'user/p@16c999e8c71134401a78d4d46435517b2271d6ac'
         result = self.conv.convert(text)
-        assert_equal(result, '[user/p@16c999]'
+        assert (result == '[user/p@16c999]'
                              '(https://github.com/user/p/commit/16c999e8c71134401a78d4d46435517b2271d6ac)')
 
     def test_convert_ticket(self):
         text = 'Ticket #1'
         result = self.conv.convert(text)
-        assert_equal(result, 'Ticket [#1]')
-        assert_equal(self.conv.convert('#1'), '[#1]')
+        assert result == 'Ticket [#1]'
+        assert self.conv.convert('#1') == '[#1]'
 
     def test_convert_user_ticket(self):
         text = 'user#1'
         result = self.conv.convert(text)
-        assert_equal(result, '[#1]')
+        assert result == '[#1]'
 
         # Not an owner of current project
         text = 'another-user#1'
         result = self.conv.convert(text)
-        assert_equal(result, 'another-user#1')
+        assert result == 'another-user#1'
 
     def test_convert_user_repo_ticket(self):
         text = 'user/project#1'
         result = self.conv.convert(text)
-        assert_equal(result, '[#1]')
+        assert result == '[#1]'
 
         # Not a current project
         text = 'user/p#1'
         result = self.conv.convert(text)
-        assert_equal(result, '[user/p#1](https://github.com/user/p/issues/1)')
+        assert result == '[user/p#1](https://github.com/user/p/issues/1)'
 
     def test_convert_strikethrough(self):
         text = '~~mistake~~'
-        assert_equal(self.conv.convert(text), '<s>mistake</s>')
+        assert self.conv.convert(text) == '<s>mistake</s>'
 
     def test_inline_code_block(self):
         text = 'This `~~some text~~` converts to this ~~strike out~~.'
         result = 'This `~~some text~~` converts to this <s>strike out</s>.'
-        assert_equal(self.conv.convert(text).strip(), result)
+        assert self.conv.convert(text).strip() == result
 
     def test_convert_code_blocks(self):
         text = '''```python
@@ -111,7 +111,7 @@ Two code blocks here!
         console.log(i);
     }'''
 
-        assert_equal(self.conv.convert(text).strip(), result)
+        assert self.conv.convert(text).strip() == result
 
     def test_code_blocks_without_newline_before(self):
         text = '''
@@ -126,9 +126,9 @@ There are some code snippet:
 
     print 'Hello'
 Pretty cool, ha?'''
-        assert_equal(self.conv.convert(text).strip(), result.strip())
+        assert self.conv.convert(text).strip() == result.strip()
         text = text.replace('```', '~~~')
-        assert_equal(self.conv.convert(text).strip(), result.strip())
+        assert self.conv.convert(text).strip() == result.strip()
 
         text = '''
 There are some code snippet:
@@ -143,4 +143,4 @@ There are some code snippet:
     :::python
     print 'Hello'
 Pretty cool, ha?'''
-        assert_equal(self.conv.convert(text).strip(), result.strip())
+        assert self.conv.convert(text).strip() == result.strip()
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index d99117d94..5afcebb17 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -118,7 +118,7 @@ class TestGitHubWikiImporter(TestCase):
             'project_name': 'me/project',
             'source_id': 'Page',
         }
-        assert_equal(page.import_id, import_id)
+        assert page.import_id == import_id
 
     @patch('forgeimporters.github.wiki.WM.Page.upsert')
     @patch('forgeimporters.github.wiki.h.render_any_markup')
@@ -132,11 +132,11 @@ class TestGitHubWikiImporter(TestCase):
         importer.app.url = '/p/test/wiki/'
         importer.rewrite_links = Mock(return_value='')
         importer._without_history(self.commit2)
-        assert_equal(upsert.call_args_list, [call('Home2'), call('Home3')])
+        assert upsert.call_args_list == [call('Home2'), call('Home3')]
 
-        assert_equal(render.call_args_list, [
+        assert render.call_args_list == [
             call('Home2.creole', '**test message**'),
-            call('Home3.rest', 'test message')])
+            call('Home3.rest', 'test message')]
 
     @patch('forgeimporters.github.wiki.git.Repo')
     @patch('forgeimporters.github.wiki.mkdtemp')
@@ -154,16 +154,16 @@ class TestGitHubWikiImporter(TestCase):
         repo = clone.return_value
         repo.iter_commits.return_value = [self.commit1, self.commit2]
         GitHubWikiImporter().import_pages('wiki_url', history=True)
-        assert_equal(with_history.call_count, 2)
-        assert_equal(without_history.call_count, 0)
+        assert with_history.call_count == 2
+        assert without_history.call_count == 0
 
     @patch('forgeimporters.github.wiki.GitHubWikiImporter._with_history')
     @patch('forgeimporters.github.wiki.GitHubWikiImporter._without_history')
     def test_get_commits_without_history(self, without_history, with_history):
         with patch('forgeimporters.github.wiki.git.Repo._clone'):
             GitHubWikiImporter().import_pages('wiki_url')
-            assert_equal(with_history.call_count, 0)
-            assert_equal(without_history.call_count, 1)
+            assert with_history.call_count == 0
+            assert without_history.call_count == 1
 
     @patch('forgeimporters.github.wiki.WM.Page.upsert')
     @patch('forgeimporters.github.wiki.h.render_any_markup')
@@ -178,8 +178,8 @@ class TestGitHubWikiImporter(TestCase):
         importer.app.url = '/p/test/wiki/'
         importer.rewrite_links = Mock(return_value='')
         importer._with_history(self.commit2)
-        assert_equal(upsert.call_args_list, [call('Home')])
-        assert_equal(render.call_args_list,
+        assert upsert.call_args_list == [call('Home')]
+        assert (render.call_args_list ==
                      [call('Home.rst', '# test message')])
 
     @skipIf(module_not_available('html2text'), 'html2text required')
@@ -198,8 +198,8 @@ class TestGitHubWikiImporter(TestCase):
         importer.rewrite_links = Mock(return_value='')
         importer.convert_gollum_tags = Mock(return_value='# test message')
         importer._with_history(self.commit2)
-        assert_equal(upsert.call_args_list, [call('Home')])
-        assert_equal(md2mkm.call_args_list, [call('# test message')])
+        assert upsert.call_args_list == [call('Home')]
+        assert md2mkm.call_args_list == [call('# test message')]
 
     def test_set_available_pages(self):
         importer = GitHubWikiImporter()
@@ -210,70 +210,70 @@ class TestGitHubWikiImporter(TestCase):
         blobs[2].name = 'code & fun.textile'
         commit.tree.traverse.return_value = blobs
         importer._set_available_pages(commit)
-        assert_equal(importer.available_pages, ['Home 42', 'code & fun'])
+        assert importer.available_pages == ['Home 42', 'code & fun']
 
     def test_gollum_page_links_case_insensitive(self):
         i = GitHubWikiImporter()
         i.available_pages = ['Home 42', 'code & fun']
-        assert_equal(i.convert_gollum_tags('[[Code & Fun]]'), '[code & fun]')
-        assert_equal(i.convert_gollum_tags('[[home-42]]'), '[Home 42]')
-        assert_equal(i.convert_gollum_tags('[[Unknown]]'), '[Unknown]')
+        assert i.convert_gollum_tags('[[Code & Fun]]') == '[code & fun]'
+        assert i.convert_gollum_tags('[[home-42]]') == '[Home 42]'
+        assert i.convert_gollum_tags('[[Unknown]]') == '[Unknown]'
 
     def test_convert_page_name(self):
         f = GitHubWikiImporter()._convert_page_name
-        assert_equal(f('Page Name'), 'Page Name')
-        assert_equal(f('Page-Name'), 'Page Name')
-        assert_equal(f('Page / Name'), 'Page   Name')
+        assert f('Page Name') == 'Page Name'
+        assert f('Page-Name') == 'Page Name'
+        assert f('Page / Name') == 'Page   Name'
 
     def test_convert_gollum_page_links(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f('[[Page]]'), '[Page]')
-        assert_equal(f('[[Page Title|Page]]'), '[Page Title](Page)')
-        assert_equal(f('[[Pagê Nâme]]'), '[Pagê Nâme]')
+        assert f('[[Page]]') == '[Page]'
+        assert f('[[Page Title|Page]]') == '[Page Title](Page)'
+        assert f('[[Pagê Nâme]]') == '[Pagê Nâme]'
         # Github always converts spaces and slashes in links to hyphens,
         # to lookup page in the filesystem. During import we're converting
         # all hyphens in page name to spaces, but still supporting both link
         # formats.
-        assert_equal(f('[[Page With Spaces]]'), '[Page With Spaces]')
-        assert_equal(f('[[Page-With-Spaces]]'), '[Page With Spaces]')
-        assert_equal(f('[[Page / 1]]'), '[Page   1]')
-        assert_equal(f('[[Title|Page With Spaces]]'),
+        assert f('[[Page With Spaces]]') == '[Page With Spaces]'
+        assert f('[[Page-With-Spaces]]') == '[Page With Spaces]'
+        assert f('[[Page / 1]]') == '[Page   1]'
+        assert (f('[[Title|Page With Spaces]]') ==
                      '[Title](Page With Spaces)')
-        assert_equal(f('[[Title|Page-With-Spaces]]'),
+        assert (f('[[Title|Page-With-Spaces]]') ==
                      '[Title](Page With Spaces)')
-        assert_equal(f('[[go here|Page / 1]]'), '[go here](Page   1)')
+        assert f('[[go here|Page / 1]]') == '[go here](Page   1)'
 
     def test_convert_gollum_page_links_escaped(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f("'[[Page]]"), '[[Page]]')
-        assert_equal(f("'[[Page Title|Page]]"), '[[Page Title|Page]]')
-        assert_equal(f("'[[Page With Spaces]]"), '[[Page With Spaces]]')
-        assert_equal(f("'[[Page-With-Spaces]]"), '[[Page-With-Spaces]]')
-        assert_equal(f("'[[Page / 1]]"), '[[Page / 1]]')
-        assert_equal(f("'[[Title|Page With Spaces]]"),
+        assert f("'[[Page]]") == '[[Page]]'
+        assert f("'[[Page Title|Page]]") == '[[Page Title|Page]]'
+        assert f("'[[Page With Spaces]]") == '[[Page With Spaces]]'
+        assert f("'[[Page-With-Spaces]]") == '[[Page-With-Spaces]]'
+        assert f("'[[Page / 1]]") == '[[Page / 1]]'
+        assert (f("'[[Title|Page With Spaces]]") ==
                      '[[Title|Page With Spaces]]')
-        assert_equal(f("'[[Title|Page-With-Spaces]]"),
+        assert (f("'[[Title|Page-With-Spaces]]") ==
                      '[[Title|Page-With-Spaces]]')
-        assert_equal(f("'[[go here|Page / 1]]"), '[[go here|Page / 1]]')
+        assert f("'[[go here|Page / 1]]") == '[[go here|Page / 1]]'
 
     def test_convert_gollum_external_links(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f('[[http://domain.net]]'), '<http://domain.net>')
-        assert_equal(f('[[https://domain.net]]'), '<https://domain.net>')
-        assert_equal(f('[[Site|http://domain.net]]'),
+        assert f('[[http://domain.net]]') == '<http://domain.net>'
+        assert f('[[https://domain.net]]') == '<https://domain.net>'
+        assert (f('[[Site|http://domain.net]]') ==
                      '[Site](http://domain.net)')
 
     def test_convert_gollum_external_links_escaped(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f("'[[http://domain.net]]"), '[[http://domain.net]]')
-        assert_equal(f("'[[https://domain.net]]"), '[[https://domain.net]]')
-        assert_equal(f("'[[Site|http://domain.net]]"),
+        assert f("'[[http://domain.net]]") == '[[http://domain.net]]'
+        assert f("'[[https://domain.net]]") == '[[https://domain.net]]'
+        assert (f("'[[Site|http://domain.net]]") ==
                      '[[Site|http://domain.net]]')
 
     def test_convert_gollum_toc(self):
         f = GitHubWikiImporter().convert_gollum_tags
-        assert_equal(f('[[_TOC_]]'), '[TOC]')
-        assert_equal(f("'[[_TOC_]]"), '[[_TOC_]]')
+        assert f('[[_TOC_]]') == '[TOC]'
+        assert f("'[[_TOC_]]") == '[[_TOC_]]'
 
     def test_convert_gollum_tags(self):
         f = GitHubWikiImporter().convert_gollum_tags
@@ -293,7 +293,7 @@ Our website is <http://domain.net>.
 
 [[Escaped Tag]]'''
 
-        assert_equal(f(source), result)
+        assert f(source) == result
 
     @skipIf(module_not_available('html2text'), 'html2text required')
     def test_convert_markup(self):
@@ -337,9 +337,9 @@ ticket [#1]
 [#1] header
 
 sha [aaaaaa]'''
-        assert_equal(f(source, 'test.md').strip(), result)
+        assert f(source, 'test.md').strip() == result
 
-        assert_equal(f('h1. Hello', 't.textile').strip(), '# Hello')
+        assert f('h1. Hello', 't.textile').strip() == '# Hello'
 
     @without_module('html2text')
     def test_convert_markup_without_html2text(self):
@@ -367,35 +367,35 @@ Our website is [[http://domain.net]].
 <p>[External link to the wiki page](https://github.com/a/b/wiki/Page)</p>
 <p>[External link](https://github.com/a/b/issues/1)</p>'''
 
-        assert_equal(f(source, 'test.textile').strip(), result)
+        assert f(source, 'test.textile').strip() == result
 
     def test_rewrite_links(self):
         f = GitHubWikiImporter().rewrite_links
         prefix = 'https://github/a/b/wiki'
         new = '/p/test/wiki/'
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/wiki/Test Page">Test Page</a>',
-              prefix, new),
+              prefix, new) ==
             '<a href="/p/test/wiki/Test Page">Test Page</a>')
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/wiki/Test-Page">Test-Page</a>',
-              prefix, new),
+              prefix, new) ==
             '<a href="/p/test/wiki/Test Page">Test Page</a>')
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/issues/1" class="1"></a>',
-              prefix, new),
+              prefix, new) ==
             '<a class="1" href="https://github/a/b/issues/1"></a>')
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/wiki/Test Page">https://github/a/b/wiki/Test Page</a>',
-              prefix, new),
+              prefix, new) ==
             '<a href="/p/test/wiki/Test Page">/p/test/wiki/Test Page</a>')
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/wiki/Test Page">Test blah blah</a>',
-              prefix, new),
+              prefix, new) ==
             '<a href="/p/test/wiki/Test Page">Test blah blah</a>')
-        assert_equal(
+        assert (
             f('<a href="https://github/a/b/wiki/Test Page">Test <b>Page</b></a>',
-              prefix, new),
+              prefix, new) ==
             '<a href="/p/test/wiki/Test Page">Test <b>Page</b></a>')
 
     @skipIf(module_not_available('html2text'), 'html2text required')
@@ -424,7 +424,7 @@ Our website is [[http://domain.net]].
 
 '''
 
-        assert_equal(f(source, 'test.mediawiki'), result)
+        assert f(source, 'test.mediawiki') == result
 
     @skipIf(module_not_available('html2text'), 'html2text required')
     def test_convert_textile_no_leading_tabs(self):
@@ -448,7 +448,7 @@ Some text 1.
 ## Header 2
 
 See [Page]'''
-        assert_equal(f(source, 'test.textile').strip(), result)
+        assert f(source, 'test.textile').strip() == result
 
     @skipIf(module_not_available('html2text'), 'html2text required')
     def test_convert_markup_with_amp_in_links(self):
@@ -460,7 +460,7 @@ See [Page]'''
         source = '[[Ticks & Leeches]]'
         result = '[Ticks & Leeches]'
         # markdown should be untouched
-        assert_equal(f(source, 'test.rst').strip(), result)
+        assert f(source, 'test.rst').strip() == result
 
     @skipIf(module_not_available('html2text'), 'html2text required')
     def test_convert_markup_textile(self):
@@ -485,12 +485,12 @@ See [Page]'''
 
 '''
 
-        assert_equal(f(source, 'test.textile'), result)
+        assert f(source, 'test.textile') == result
 
         # textile-style links converts normal
         source = '*"Textile":Troubleshooting*'
         result = '**[Textile](Troubleshooting)**\n\n'
-        assert_equal(f(source, 'test2.textile'), result)
+        assert f(source, 'test2.textile') == result
 
         # links with formatting converts normal in textile now
         source = '''*[[this checklist|Troubleshooting]]*
@@ -506,7 +506,7 @@ some text and **[Tips n\u2019 Tricks]**
 **[link](http://otherlink.com)**
 
 '''
-        assert_equal(f(source, 'test3.textile'), result)
+        assert f(source, 'test3.textile') == result
 
     @skipIf(module_not_available('html2text'), 'html2text required')
     def test_convert_textile_special_tag(self):
@@ -516,7 +516,7 @@ some text and **[Tips n\u2019 Tricks]**
         importer.app.url = '/p/test/wiki/'
         f = importer.convert_markup
         source = '*[[this checklist|Troubleshooting]]*'
-        assert_equal(f(source, 't.textile').strip(),
+        assert (f(source, 't.textile').strip() ==
                      '**[this checklist](Troubleshooting)**')
 
     @without_module('html2text')
@@ -528,7 +528,7 @@ some text and **[Tips n\u2019 Tricks]**
         f = importer.convert_markup
         source = '*[[this checklist|Troubleshooting]]*'
         result = '<p><strong>[[this checklist|Troubleshooting]]</strong></p>'
-        assert_equal(f(source, 't.textile').strip(), result)
+        assert f(source, 't.textile').strip() == result
 
     @patch('forgeimporters.github.wiki.mkdtemp', autospec=True)
     @patch('forgeimporters.github.wiki.rmtree', autospec=True)
@@ -536,7 +536,7 @@ some text and **[Tips n\u2019 Tricks]**
     def test_has_wiki_repo(self, repo, rmtree, mkdtemp):
         mkdtemp.return_value = 'fake path'
         i = GitHubWikiImporter()
-        assert_equal(i.has_wiki_repo('fake url'), True)
+        assert i.has_wiki_repo('fake url') == True
         repo.clone_from.assert_called_once_with(
             'fake url', to_path='fake path', bare=True)
         rmtree.assert_called_once_with('fake path')
@@ -544,7 +544,7 @@ some text and **[Tips n\u2019 Tricks]**
         def raise_error(*args, **kw):
             raise git.GitCommandError('bam', 'bam', 'bam')
         repo.clone_from.side_effect = raise_error
-        assert_equal(i.has_wiki_repo('fake url'), False)
+        assert i.has_wiki_repo('fake url') == False
 
 
 class TestGitHubWikiImportController(TestController, TestCase):
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
index 57cb9b228..78dd617bf 100644
--- a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -62,16 +62,16 @@ class TestGitHubOAuth(TestController):
         oauth.return_value = oauth_instance
 
         user = M.User.by_username('test-admin')
-        assert_equal(user.get_tool_data('GitHubProjectImport', 'token'), None)
+        assert user.get_tool_data('GitHubProjectImport', 'token') == None
         r = self.app.get('/p/import_project/github/')
-        assert_equal(r.status_int, 302)
-        assert_equal(r.location, redirect)
+        assert r.status_int == 302
+        assert r.location == redirect
         session.__setitem__.assert_has_calls([
             call('github.oauth.state', 'state'),
             call('github.oauth.redirect',
                  'http://localhost/p/import_project/github/')
         ])
-        assert_equal(session.save.call_count, 1)
+        assert session.save.call_count == 1
 
         r = self.app.get(redirect)
         session.get.assert_has_calls([
@@ -79,14 +79,14 @@ class TestGitHubOAuth(TestController):
             call('github.oauth.redirect', '/')
         ])
         user = M.User.by_username('test-admin')
-        assert_equal(user.get_tool_data('GitHubProjectImport', 'token'), 'abc')
+        assert user.get_tool_data('GitHubProjectImport', 'token') == 'abc'
 
         with patch('forgeimporters.github.requests.post') as valid_access_token_post:
             valid_access_token_post.return_value = Mock(status_code=200)
             r = self.app.get('/p/import_project/github/')
 
         # token in user data, so oauth isn't triggered
-        assert_equal(r.status_int, 200)
+        assert r.status_int == 200
 
         valid_access_token_post.assert_called_once_with('https://api.github.com/applications/client_id/token',
                                                         auth=requests.auth.HTTPBasicAuth('client_id', 'secret'),
@@ -96,5 +96,5 @@ class TestGitHubOAuth(TestController):
 
     def test_project_import_login_required(self):
         r = self.app.get('/p/import_project/github/', extra_environ=dict(username='*anonymous'))
-        assert_equal(None, r.location)
+        assert None == r.location
         r.mustcontain('Login Required')
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index 44595cb86..b5d6dbe74 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -317,7 +317,7 @@ class TestProjectToolsImportController(TestController):
             import1_page = import_main_page.click('Import', href=r'importer1$')
         url = import1_page.request.path
         assert url.endswith('/admin/ext/import/importer1'), url
-        assert_equal(import1_page.text, 'test importer 1 controller webpage')
+        assert import1_page.text == 'test importer 1 controller webpage'
 
     @mock.patch.object(base.h, 'iter_entry_points')
     def test_hidden(self, iep):
@@ -344,16 +344,16 @@ def test_get_importer_upload_path():
         neighborhood=mock.Mock(url_prefix='p/'),
     )
     with h.push_config(config, importer_upload_path='path/{nbhd}/{project}'):
-        assert_equal(base.get_importer_upload_path(project), 'path/p/prefix')
+        assert base.get_importer_upload_path(project) == 'path/p/prefix'
         project.is_nbhd_project = True
-        assert_equal(base.get_importer_upload_path(project), 'path/p/n_url')
+        assert base.get_importer_upload_path(project) == 'path/p/n_url'
         project.is_nbhd_project = False
         project.is_user_project = True
-        assert_equal(base.get_importer_upload_path(project),
+        assert (base.get_importer_upload_path(project) ==
                      'path/p/shortname')
         project.is_user_project = False
         project.is_root = True
-        assert_equal(base.get_importer_upload_path(project),
+        assert (base.get_importer_upload_path(project) ==
                      'path/p/prefix/shortname')
 
 
@@ -385,7 +385,7 @@ class TestFile:
             'data': 'data',
         }
         f = base.File('http://example.com/barbaz.jpg')
-        assert_equal(f.type, 'image/jpeg')
+        assert f.type == 'image/jpeg'
 
         f = base.File('http://example.com/barbaz')
-        assert_equal(f.type, 'image/png')
+        assert f.type == 'image/png'
diff --git a/ForgeLink/forgelink/tests/functional/test_rest.py b/ForgeLink/forgelink/tests/functional/test_rest.py
index 4ec59b71e..d420d537a 100644
--- a/ForgeLink/forgelink/tests/functional/test_rest.py
+++ b/ForgeLink/forgelink/tests/functional/test_rest.py
@@ -34,20 +34,20 @@ class TestLinkApi(TestRestApiBase):
 
     def test_rest_link(self):
         r = self.api_get('/rest/p/test/link')
-        assert_equal(r.json['url'], None)
+        assert r.json['url'] == None
 
         r = self.api_post('/rest/p/test/link',
                           url='http://google.com')
-        assert_equal(r.json['url'], 'http://google.com')
+        assert r.json['url'] == 'http://google.com'
 
         self.api_post('/rest/p/test/link',
                       url='http://yahoo.com')
         r = self.api_get('/rest/p/test/link')
-        assert_equal(r.json['url'], 'http://yahoo.com')
+        assert r.json['url'] == 'http://yahoo.com'
 
         self.api_post('/rest/p/test/link')
         r = self.api_get('/rest/p/test/link')
-        assert_equal(r.json['url'], 'http://yahoo.com')
+        assert r.json['url'] == 'http://yahoo.com'
 
     def test_rest_link_get_permissions(self):
         self.app.get('/rest/p/test/link',
@@ -75,7 +75,7 @@ class TestLinkApi(TestRestApiBase):
                       extra_environ={'username': '*anonymous'},
                       status=200)
         r = self.api_get('/rest/p/test/link')
-        assert_equal(r.json['url'], 'http://yahoo.com')
+        assert r.json['url'] == 'http://yahoo.com'
 
 
 class TestLinkHasAccess(TestRestApiBase):
@@ -98,13 +98,13 @@ class TestLinkHasAccess(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/link/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/link/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -120,10 +120,10 @@ class TestLinkHasAccess(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/link/has_access?user=test-admin&perm=configure',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/link/has_access?user=test-user&perm=configure',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
diff --git a/ForgeLink/forgelink/tests/functional/test_root.py b/ForgeLink/forgelink/tests/functional/test_root.py
index 31b570d96..595c2aa46 100644
--- a/ForgeLink/forgelink/tests/functional/test_root.py
+++ b/ForgeLink/forgelink/tests/functional/test_root.py
@@ -37,7 +37,7 @@ class TestRootController(TestController):
         response.form['url'] = 'http://www.google.com/'
         response.form.submit()
         redir = self.app.get('/link/index', status=302)
-        assert_equal(redir.location, 'http://www.google.com/')
+        assert redir.location == 'http://www.google.com/'
 
     @td.with_link
     def test_root_with_url(self):
@@ -45,7 +45,7 @@ class TestRootController(TestController):
         response.form['url'] = 'http://www.google.com/'
         response.form.submit()
         redir = self.app.get('/link', status=302)
-        assert_equal(redir.location, 'http://www.google.com/')
+        assert redir.location == 'http://www.google.com/'
 
     @td.with_link
     def test_root_suffix_with_url_slash(self):
@@ -53,7 +53,7 @@ class TestRootController(TestController):
         response.form['url'] = 'http://www.google.com/'
         response.form.submit()
         redir = self.app.get('/link/service', status=302)
-        assert_equal(redir.location, 'http://www.google.com/service')
+        assert redir.location == 'http://www.google.com/service'
 
     @td.with_link
     def test_root_suffix_with_url_value(self):
@@ -61,7 +61,7 @@ class TestRootController(TestController):
         response.form['url'] = 'http://www.google.de/search?q='
         response.form.submit()
         redir = self.app.get(h.urlquote('/link/helpåß'), status=302)
-        assert_equal(redir.location, 'http://www.google.de/search?q=help%C3%A5%C3%9F')
+        assert redir.location == 'http://www.google.de/search?q=help%C3%A5%C3%9F'
 
 
 class TestConfigOptions(TestController):
@@ -72,7 +72,7 @@ class TestConfigOptions(TestController):
 
     def assert_url(self, mount_point, val):
         app = self.project.app_instance(mount_point)
-        assert_equal(app.config.options['url'], val)
+        assert app.config.options['url'] == val
 
     def test_sets_url_on_install(self):
         r = self.app.post('/p/test/admin/update_mounts', params={
@@ -93,17 +93,17 @@ class TestConfigOptions(TestController):
             'new.mount_label': 'Google',
             'url': 'invalid url'})
         flash = json.loads(self.webflash(r))
-        assert_equal(flash['status'], 'error')
-        assert_equal(flash['message'], 'ToolError: url: That is not a valid URL')
+        assert flash['status'] == 'error'
+        assert flash['message'] == 'ToolError: url: That is not a valid URL'
         app = self.project.app_instance('link-google')
-        assert_equal(app, None)
+        assert app == None
 
     @td.with_link
     def test_sets_url_on_config(self):
         self.assert_url('link', None)
         params = {'url': 'https://allura.apache.org'}
         r = self.app.post('/p/test/admin/link/configure', params=params)
-        assert_equal(self.webflash(r), '')
+        assert self.webflash(r) == ''
         self.assert_url('link', 'https://allura.apache.org')
 
     @td.with_link
@@ -112,28 +112,28 @@ class TestConfigOptions(TestController):
         params = {'url': 'invalid link'}
         r = self.app.post('/p/test/admin/link/configure', params=params)
         flash = json.loads(self.webflash(r))
-        assert_equal(flash['status'], 'error')
-        assert_equal(flash['message'], 'url: That is not a valid URL')
+        assert flash['status'] == 'error'
+        assert flash['message'] == 'url: That is not a valid URL'
         self.assert_url('link', None)
 
     @td.with_link
     def test_menu_url(self):
         resp = self.app.get('/p/test/admin/')
-        assert_in('/p/test/link/', str(resp.html.find(id='top_nav')))
+        assert '/p/test/link/' in str(resp.html.find(id='top_nav'))
 
         response = self.app.get('/admin/link/options')
         response.form['url'] = 'http://foo.bar/baz'
         response.form.submit()
 
         resp = self.app.get('/p/test/admin/')
-        assert_in('http://foo.bar/baz', str(resp.html.find(id='top_nav')))
+        assert 'http://foo.bar/baz' in str(resp.html.find(id='top_nav'))
 
     def _check_configurable(self, admin_nav_data):
         for menu_item in admin_nav_data['menu']:
             if menu_item['tool_name'] == 'link':
-                assert_in({'className': 'admin_modal',
+                assert ({'className': 'admin_modal',
                            'text': 'Options',
-                           'href': '/p/test/admin/link/options'},
+                           'href': '/p/test/admin/link/options'} in
                           menu_item['admin_options'])
                 break
         else:
diff --git a/ForgeLink/forgelink/tests/test_app.py b/ForgeLink/forgelink/tests/test_app.py
index 6ff4d5b1b..28efa0054 100644
--- a/ForgeLink/forgelink/tests/test_app.py
+++ b/ForgeLink/forgelink/tests/test_app.py
@@ -43,4 +43,4 @@ class TestBulkExport:
         f = tempfile.TemporaryFile('w+')
         link.bulk_export(f)
         f.seek(0)
-        assert_equal(json.loads(f.read())['url'], 'http://domain.net')
+        assert json.loads(f.read())['url'] == 'http://domain.net'
diff --git a/ForgeSVN/forgesvn/tests/functional/test_auth.py b/ForgeSVN/forgesvn/tests/functional/test_auth.py
index 992613e91..6ae98a74f 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_auth.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_auth.py
@@ -27,19 +27,19 @@ class TestSVNAuth(TestController):
     @with_svn
     def test_refresh_repo(self):
         r = self.app.get('/auth/refresh_repo')
-        assert_equal(r.text, 'No repo specified')
+        assert r.text == 'No repo specified'
 
         r = self.app.get('/auth/refresh_repo/p/gbalksdfh')
-        assert_equal(r.text, 'No project at /p/gbalksdfh')
+        assert r.text == 'No project at /p/gbalksdfh'
 
         r = self.app.get('/auth/refresh_repo/p/test')
-        assert_equal(r.text, '/p/test does not include a repo mount point')
+        assert r.text == '/p/test does not include a repo mount point'
 
         r = self.app.get('/auth/refresh_repo/p/test/blah/')
-        assert_equal(r.text, 'Cannot find repo at /p/test/blah')
+        assert r.text == 'Cannot find repo at /p/test/blah'
 
         r = self.app.get('/auth/refresh_repo/p/test/src/')
-        assert_equal(r.text,
+        assert (r.text ==
                      '<Repository /tmp/svn/p/test/src> refresh queued.\n')
 
 
@@ -52,6 +52,6 @@ class TestSVNUserPermissions(TestController):
     def test_list_repos(self):
         r = self.app.get('/auth/repo_permissions',
                          params=dict(username='test-admin'), status=200)
-        assert_equal(json.loads(r.text), {"allow_write": [
+        assert json.loads(r.text) == {"allow_write": [
             '/svn/test/src',
-        ]})
+        ]}
diff --git a/ForgeSVN/forgesvn/tests/functional/test_controllers.py b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
index 1644b20cc..1a4cbe637 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -101,42 +101,42 @@ class TestRootController(SVNTestController):
     def test_commit_browser_data(self):
         resp = self.app.get('/src/commit_browser_data')
         data = json.loads(resp.text)
-        assert_equal(data['max_row'], 6)
-        assert_equal(data['next_column'], 1)
+        assert data['max_row'] == 6
+        assert data['next_column'] == 1
         for val in data['built_tree'].values():
             if val['url'] == '/p/test/src/1/':
-                assert_equal(val['short_id'], '[r1]')
-                assert_equal(val['column'], 0)
-                assert_equal(val['row'], 6)
-                assert_equal(val['message'], 'Create readme')
+                assert val['short_id'] == '[r1]'
+                assert val['column'] == 0
+                assert val['row'] == 6
+                assert val['message'] == 'Create readme'
 
     def test_feed(self):
         for ext in ['', '.rss']:
             r = self.app.get('/src/feed%s' % ext)
             channel = r.xml.find('channel')
             title = channel.find('title').text
-            assert_equal(title, 'test SVN changes')
+            assert title == 'test SVN changes'
             description = channel.find('description').text
-            assert_equal(description,
+            assert (description ==
                          'Recent changes to SVN repository in test project')
             link = channel.find('link').text
-            assert_equal(link, 'http://localhost/p/test/src/')
+            assert link == 'http://localhost/p/test/src/'
             earliest_commit = channel.findall('item')[-1]
-            assert_equal(earliest_commit.find('title').text, 'Create readme')
+            assert earliest_commit.find('title').text == 'Create readme'
             link = 'http://localhost/p/test/src/1/'
-            assert_equal(earliest_commit.find('link').text, link)
-            assert_equal(earliest_commit.find('guid').text, link)
+            assert earliest_commit.find('link').text == link
+            assert earliest_commit.find('guid').text == link
         # .atom has slightly different structure
         prefix = '{http://www.w3.org/2005/Atom}'
         r = self.app.get('/src/feed.atom')
         title = r.xml.find(prefix + 'title').text
-        assert_equal(title, 'test SVN changes')
+        assert title == 'test SVN changes'
         link = r.xml.find(prefix + 'link').attrib['href']
-        assert_equal(link, 'http://localhost/p/test/src/')
+        assert link == 'http://localhost/p/test/src/'
         earliest_commit = r.xml.findall(prefix + 'entry')[-1]
-        assert_equal(earliest_commit.find(prefix + 'title').text, 'Create readme')
+        assert earliest_commit.find(prefix + 'title').text == 'Create readme'
         link = 'http://localhost/p/test/src/1/'
-        assert_equal(earliest_commit.find(prefix + 'link').attrib['href'], link)
+        assert earliest_commit.find(prefix + 'link').attrib['href'] == link
 
     def test_commit(self):
         resp = self.app.get('/src/3/tree/')
@@ -146,7 +146,7 @@ class TestRootController(SVNTestController):
         resp = self.app.get('/src/6/')
         file_url = resp.html.find("a", string="/ЗРЯЧИЙ_ТА_ПОБАЧИТЬ")['href']
         resp = self.app.get(file_url)
-        assert_in('This is readme',  # same content as the README file actually
+        assert ('This is readme' in  # same content as the README file actually
                   resp.html.select_one('.codebrowser').text)
 
         resp = self.app.get('/src/7/')
@@ -154,22 +154,22 @@ class TestRootController(SVNTestController):
             '\n\t'.join(str(t) for t in resp.html.select('.inline-diff a'))))
         file_url = resp.html.find("a", string="/with%2Furlquote-literal.txt")['href']
         file_resp = self.app.get(file_url)
-        assert_in('%2F means /',
+        assert ('%2F means /' in
                   file_resp.html.select_one('.codebrowser').text)
 
         file_url = resp.html.find("a", string='/with-percent%.txt')['href']
         file_resp = self.app.get(file_url)
-        assert_in('%%%',
+        assert ('%%%' in
                   file_resp.html.select_one('.codebrowser').text)
 
         file_url = resp.html.find("a", string="/with space.txt")['href']
         file_resp = self.app.get(file_url)
-        assert_in('spaces',
+        assert ('spaces' in
                   file_resp.html.select_one('.codebrowser').text)
 
         file_url = resp.html.find("a", string='/with"&:specials.txt')['href']
         file_resp = self.app.get(file_url)
-        assert_in('"&: encodes as %22%26%3A',
+        assert ('"&: encodes as %22%26%3A' in
                   file_resp.html.select_one('.codebrowser').text)
 
     def test_tree(self):
@@ -262,39 +262,39 @@ class TestRootController(SVNTestController):
         shutil.rmtree(c.app.repo.tarball_path, ignore_errors=True)
         r = self.app.get('/p/test/svn-tags/19/tree/')
         form = r.html.find('form', 'tarball')
-        assert_equal(form.button.text, '\xa0Download Snapshot')
-        assert_equal(form.get('action'), '/p/test/svn-tags/19/tarball')
+        assert form.button.text == '\xa0Download Snapshot'
+        assert form.get('action') == '/p/test/svn-tags/19/tarball'
 
         r = self.app.get('/p/test/svn-tags/19/tree/tags/tag-1.0/')
         form = r.html.find('form', 'tarball')
-        assert_equal(form.button.text, '\xa0Download Snapshot')
-        assert_equal(form.get('action'), '/p/test/svn-tags/19/tarball')
-        assert_equal(form.find('input', attrs=dict(name='path')).get('value'), '/tags/tag-1.0')
+        assert form.button.text == '\xa0Download Snapshot'
+        assert form.get('action') == '/p/test/svn-tags/19/tarball'
+        assert form.find('input', attrs=dict(name='path')).get('value') == '/tags/tag-1.0'
 
         r = self.app.get('/p/test/svn-tags/19/tarball_status?path=/tags/tag-1.0')
-        assert_equal(r.json['status'], None)
+        assert r.json['status'] == None
         r = self.app.post('/p/test/svn-tags/19/tarball',
                           dict(path='/tags/tag-1.0')).follow()
         assert 'Generating snapshot...' in r
         M.MonQTask.run_ready()
         r = self.app.get('/p/test/svn-tags/19/tarball_status?path=/tags/tag-1.0')
-        assert_equal(r.json['status'], 'complete')
+        assert r.json['status'] == 'complete'
 
         r = self.app.get('/p/test/svn-tags/19/tarball_status?path=/trunk')
-        assert_equal(r.json['status'], None)
+        assert r.json['status'] == None
         r = self.app.post('/p/test/svn-tags/19/tarball',
                           dict(path='/trunk/')).follow()
         assert 'Generating snapshot...' in r
         M.MonQTask.run_ready()
         r = self.app.get('/p/test/svn-tags/19/tarball_status?path=/trunk')
-        assert_equal(r.json['status'], 'complete')
+        assert r.json['status'] == 'complete'
 
         r = self.app.get('/p/test/svn-tags/19/tarball_status?path=/branches/aaa/')
-        assert_equal(r.json['status'], None)
+        assert r.json['status'] == None
 
         # this is is the same as trunk snapshot, so it's ready already
         r = self.app.get('/p/test/svn-tags/19/tarball_status')
-        assert_equal(r.json['status'], 'complete')
+        assert r.json['status'] == 'complete'
 
 
 class TestImportController(SVNTestController):
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 8451b4341..9d5e02856 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -82,25 +82,25 @@ class TestNewRepo(unittest.TestCase):
         assert self.rev.index_id().startswith('allura/model/repo/Commit#')
         self.rev.author_url
         self.rev.committer_url
-        assert_equal(self.rev.tree._id, self.rev.tree_id)
-        assert_equal(self.rev.shorthand_id(), f'[r{latest_rev}]')
-        assert_equal(self.rev.symbolic_ids, ([], []))
-        assert_equal(self.rev.url(), f'/p/test/src/{latest_rev}/')
+        assert self.rev.tree._id == self.rev.tree_id
+        assert self.rev.shorthand_id() == f'[r{latest_rev}]'
+        assert self.rev.symbolic_ids == ([], [])
+        assert self.rev.url() == f'/p/test/src/{latest_rev}/'
         all_cis = list(self.repo.log(self.rev._id, limit=25))
-        assert_equal(len(all_cis), latest_rev)
+        assert len(all_cis) == latest_rev
         self.rev.tree.ls()
-        assert_equal(self.rev.tree.readme(), ('README', 'This is readme\nAnother Line\n'))
-        assert_equal(self.rev.tree.path(), '/')
-        assert_equal(self.rev.tree.url(), f'/p/test/src/{latest_rev}/tree/')
+        assert self.rev.tree.readme() == ('README', 'This is readme\nAnother Line\n')
+        assert self.rev.tree.path() == '/'
+        assert self.rev.tree.url() == f'/p/test/src/{latest_rev}/tree/'
         self.rev.tree.by_name['README']
         assert self.rev.tree.is_blob('README') is True
-        assert_equal(self.rev.tree['a']['b']['c'].ls(), [])
+        assert self.rev.tree['a']['b']['c'].ls() == []
         self.assertRaises(KeyError, lambda: self.rev.tree['a']['b']['d'])
 
-        assert_equal(self.rev.authored_user, None)
-        assert_equal(self.rev.committed_user, None)
-        assert_equal(
-            sorted(self.rev.webhook_info.keys()),
+        assert self.rev.authored_user == None
+        assert self.rev.committed_user == None
+        assert (
+            sorted(self.rev.webhook_info.keys()) ==
             sorted(['id', 'url', 'timestamp', 'message', 'author',
                     'committer', 'added', 'removed', 'renamed', 'modified', 'copied']))
 
@@ -235,11 +235,11 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
     def test_log_id_only(self):
         entries = list(self.repo.log(id_only=True, limit=25))
-        assert_equal(entries, [7, 6, 5, 4, 3, 2, 1])
+        assert entries == [7, 6, 5, 4, 3, 2, 1]
 
     def test_log(self):
         entries = list(self.repo.log(id_only=False, limit=25))
-        assert_equal(entries[len(entries)-6:],  # only 6, so this test doesn't have to change when commits added
+        assert (entries[len(entries)-6:] ==  # only 6, so this test doesn't have to change when commits added
                      [
             {'parents': [5],
              'refs': [],
@@ -327,7 +327,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
     def test_log_file(self):
         entries = list(self.repo.log(path='/README', id_only=False, limit=25))
-        assert_equal(entries, [
+        assert entries == [
             {'authored': {'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
                           'email': '',
                           'name': 'rick446'},
@@ -352,7 +352,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
              'refs': [],
              'size': 15,
              'rename_details': {}},
-        ])
+        ]
 
     def test_is_file(self):
         assert self.repo.is_file('/README')
@@ -407,9 +407,9 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
     def test_diff_copy(self):
         entry = self.repo.commit(next(self.repo.log(5, id_only=True, limit=1)))
-        assert_equals(dict(entry.diffs), dict(
+        assert dict(entry.diffs) == dict(
                 copied=[{'new': '/b', 'old': '/a', 'ratio': 1}],  renamed=[],
-                changed=[], removed=[], added=[], total=1))
+                changed=[], removed=[], added=[], total=1)
 
     def test_commit(self):
         entry = self.repo.commit(1)
@@ -432,16 +432,16 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
     @skipUnless(os.path.exists(tg.config.get('scm.repos.tarball.zip_binary', '/usr/bin/zip')), 'zip binary is missing')
     def test_tarball(self):
         tmpdir = tg.config['scm.repos.tarball.root']
-        assert_equal(self.repo.tarball_path,
+        assert (self.repo.tarball_path ==
                      os.path.join(tmpdir, 'svn/t/te/test/testsvn'))
-        assert_equal(self.repo.tarball_url('1'),
+        assert (self.repo.tarball_url('1') ==
                      'file:///svn/t/te/test/testsvn/test-src-r1.zip')
         self.repo.tarball('1')
         assert os.path.isfile(
             os.path.join(tmpdir, "svn/t/te/test/testsvn/test-src-r1.zip"))
         tarball_zip = ZipFile(
             os.path.join(tmpdir, 'svn/t/te/test/testsvn/test-src-r1.zip'), 'r')
-        assert_equal(tarball_zip.namelist(),
+        assert (tarball_zip.namelist() ==
                      ['test-src-r1/', 'test-src-r1/README'])
         shutil.rmtree(self.repo.tarball_path.encode('utf-8'),
                       ignore_errors=True)
@@ -461,7 +461,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         tag_content = sorted(['test-svn-tags-r19-tags-tag-1.0/',
                               'test-svn-tags-r19-tags-tag-1.0/svn-commit.tmp',
                               'test-svn-tags-r19-tags-tag-1.0/README'])
-        assert_equal(sorted(snapshot.namelist()), tag_content)
+        assert sorted(snapshot.namelist()) == tag_content
         os.remove(fn)
 
         # a directory (of tags)
@@ -473,7 +473,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                                'test-svn-tags-r19-tags/tag-1.0/',
                                'test-svn-tags-r19-tags/tag-1.0/svn-commit.tmp',
                                'test-svn-tags-r19-tags/tag-1.0/README'])
-        assert_equal(sorted(snapshot.namelist()), tags_content)
+        assert sorted(snapshot.namelist()) == tags_content
         os.remove(fn)
 
         # no path, but there are trunk in the repo
@@ -487,7 +487,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                                 'test-svn-tags-r19-trunk/bbb.txt',
                                 'test-svn-tags-r19-trunk/ccc.txt',
                                 'test-svn-tags-r19-trunk/README'])
-        assert_equal(sorted(snapshot.namelist()), trunk_content)
+        assert sorted(snapshot.namelist()) == trunk_content
         os.remove(fn)
 
         # no path, and no trunk dir
@@ -497,7 +497,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         self.repo.tarball('1')
         assert os.path.isfile(fn), fn
         snapshot = ZipFile(fn, 'r')
-        assert_equal(snapshot.namelist(), ['test-src-r1/', 'test-src-r1/README'])
+        assert snapshot.namelist() == ['test-src-r1/', 'test-src-r1/README']
         shutil.rmtree(os.path.join(tmpdir, 'svn/t/te/test/testsvn/'),
                       ignore_errors=True)
         shutil.rmtree(tarball_path, ignore_errors=True)
@@ -568,7 +568,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                 'url': 'http://localhost/p/test/src/',
             },
         }
-        assert_equals(payload, expected_payload)
+        assert payload == expected_payload
 
 
 class TestSVNRev(unittest.TestCase):
@@ -614,17 +614,17 @@ class TestSVNRev(unittest.TestCase):
     def test_log(self):
         # path only
         commits = list(self.repo.log(self.repo.head, id_only=True, limit=25))
-        assert_equal(commits, [7, 6, 5, 4, 3, 2, 1])
+        assert commits == [7, 6, 5, 4, 3, 2, 1]
         commits = list(self.repo.log(self.repo.head, 'README', id_only=True, limit=25))
-        assert_equal(commits, [3, 1])
+        assert commits == [3, 1]
         commits = list(self.repo.log(1, 'README', id_only=True, limit=25))
-        assert_equal(commits, [1])
+        assert commits == [1]
         commits = list(self.repo.log(self.repo.head, 'a/b/c/', id_only=True, limit=25))
-        assert_equal(commits, [4, 2])
+        assert commits == [4, 2]
         commits = list(self.repo.log(3, 'a/b/c/', id_only=True, limit=25))
-        assert_equal(commits, [2])
-        assert_equal(
-            list(self.repo.log(self.repo.head, 'does/not/exist', id_only=True, limit=25)), [])
+        assert commits == [2]
+        assert (
+            list(self.repo.log(self.repo.head, 'does/not/exist', id_only=True, limit=25)) == [])
 
     def test_notification_email(self):
         setup_global_objects()
@@ -644,8 +644,8 @@ class TestSVNRev(unittest.TestCase):
         n = M.Notification.query.find({'subject': '[test:src] New commit [r1] by rick446'}).first()
 
         assert n
-        assert_in('By rick446', n.text)
-        assert_in('Create readme', n.text)
+        assert 'By rick446' in n.text
+        assert 'Create readme' in n.text
 
 
 class _Test(unittest.TestCase):
@@ -770,12 +770,12 @@ class TestRepo(_TestWithRepo):
         assert i['name_s'] == 'test1', i
 
     def test_scm_host_url(self):
-        assert_equal(self.repo.clone_url('rw', 'nobody'),
+        assert (self.repo.clone_url('rw', 'nobody') ==
                      'svn+ssh://nobody@localhost:8022/scm-repo/p/test/test1/')
-        assert_equal(self.repo.clone_url('https', 'nobody'),
+        assert (self.repo.clone_url('https', 'nobody') ==
                      'https://nobody@localhost:8022/scm-repo/p/test/test1/')
         with h.push_config(self.repo.app.config.options, external_checkout_url='https://$username@foo.com/'):
-            assert_equal(self.repo.clone_url('https', 'user'),
+            assert (self.repo.clone_url('https', 'user') ==
                          'https://user@foo.com/')
 
     def test_guess_type(self):
@@ -821,8 +821,8 @@ class TestRepo(_TestWithRepo):
         notifications = M.Notification.query.find().all()
         for n in notifications:
             if '100 new commits' in n.subject:
-                assert_in('By Test Committer on 10/08/2010 15:32', n.text)
-                assert_in('http://localhost/ci/foo99/', n.text)
+                assert 'By Test Committer on 10/08/2010 15:32' in n.text
+                assert 'http://localhost/ci/foo99/' in n.text
                 break
         else:
             assert False, 'Did not find notification'
@@ -945,7 +945,7 @@ class TestCommit(_TestWithRepo):
             'removed': [],
             'total': 5,
         }
-        assert_equal(self.ci.diffs.added,
+        assert (self.ci.diffs.added ==
                      ['a', 'a/a', 'a/a/a', 'a/a/b', 'a/b'])
         assert (self.ci.diffs.copied
                 == self.ci.diffs.changed
@@ -969,8 +969,8 @@ class TestCommit(_TestWithRepo):
             'removed': ['a', 'a/a', 'a/a/a', 'a/a/b', 'a/b'],
             'total': 10,
         }
-        assert_equal(ci.diffs.added, ['b', 'b/a', 'b/a/a', 'b/a/b', 'b/b'])
-        assert_equal(ci.diffs.removed, ['a', 'a/a', 'a/a/a', 'a/a/b', 'a/b'])
+        assert ci.diffs.added == ['b', 'b/a', 'b/a/a', 'b/a/b', 'b/b']
+        assert ci.diffs.removed == ['a', 'a/a', 'a/a/a', 'a/a/b', 'a/b']
         assert (ci.diffs.copied
                 == ci.diffs.changed
                 == [])
@@ -1004,17 +1004,17 @@ class TestCommit(_TestWithRepo):
             'renamed': [],
             'total': 2
         }
-        assert_equal(ci.diffs.added, ['b/a/z', 'b/c'])
-        assert_equal(ci.diffs.changed, [])
-        assert_equal(ci.diffs.removed, ['/b/a/b', 'b/b'])
+        assert ci.diffs.added == ['b/a/z', 'b/c']
+        assert ci.diffs.changed == []
+        assert ci.diffs.removed == ['/b/a/b', 'b/b']
         # see mock for open_blob
-        assert_equal(len(ci.diffs.copied), 2)
-        assert_equal(ci.diffs.copied[1]['old'], 'b/a/b')
-        assert_equal(ci.diffs.copied[1]['new'], 'b/c')
-        assert_equal(ci.diffs.copied[1]['ratio'], 1)
-        assert_equal(ci.diffs.copied[1]['diff'], '')
-        assert_equal(ci.diffs.copied[0]['old'], 'b/b')
-        assert_equal(ci.diffs.copied[0]['new'], 'b/a/z')
+        assert len(ci.diffs.copied) == 2
+        assert ci.diffs.copied[1]['old'] == 'b/a/b'
+        assert ci.diffs.copied[1]['new'] == 'b/c'
+        assert ci.diffs.copied[1]['ratio'] == 1
+        assert ci.diffs.copied[1]['diff'] == ''
+        assert ci.diffs.copied[0]['old'] == 'b/b'
+        assert ci.diffs.copied[0]['new'] == 'b/a/z'
 
     def test_context(self):
         self.ci.context()
@@ -1042,19 +1042,18 @@ class TestRename(unittest.TestCase):
 
     def test_log_file_with_rename(self):
         entry = list(self.repo.log(path='/dir/b.txt', id_only=False, limit=1))[0]
-        assert_equal(entry['id'], 3)
-        assert_equal(entry['rename_details']['path'], '/dir/a.txt')
-        assert_equal(
-            entry['rename_details']['commit_url'],
-            self.repo.url_for_commit(2)  # previous revision
-        )
+        assert entry['id'] == 3
+        assert entry['rename_details']['path'] == '/dir/a.txt'
+        assert (
+            entry['rename_details']['commit_url'] ==
+            self.repo.url_for_commit(2))
 
     def test_check_changed_path(self):
         changed_path = {'copyfrom_path': '/test/path', 'path': '/test/path2'}
         result = self.repo._impl._check_changed_path(
             changed_path, '/test/path2/file.txt')
-        assert_equal({'path': '/test/path2/file.txt',
-                     'copyfrom_path': '/test/path/file.txt'}, result)
+        assert {'path': '/test/path2/file.txt',
+                     'copyfrom_path': '/test/path/file.txt'} == result
 
 
 class TestDirectRepoAccess:
@@ -1088,7 +1087,7 @@ class TestDirectRepoAccess:
             'renamed': [],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         _id = self.repo._impl._oid(2)
         diffs = self.repo.commit(_id).diffs
@@ -1100,7 +1099,7 @@ class TestDirectRepoAccess:
             'copied': [],
             'total': 4,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         _id = self.repo._impl._oid(3)
         diffs = self.repo.commit(_id).diffs
@@ -1112,7 +1111,7 @@ class TestDirectRepoAccess:
             'copied': [],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
 
         _id = self.repo._impl._oid(4)
         diffs = self.repo.commit(_id).diffs
@@ -1124,4 +1123,4 @@ class TestDirectRepoAccess:
             'copied': [],
             'total': 1,
         }
-        assert_equals(diffs, expected)
+        assert diffs == expected
diff --git a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
index 769ce1a82..0667d1fdc 100644
--- a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
+++ b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
@@ -51,8 +51,8 @@ class TestSVNImplementation:
 
         tree_id = impl.compute_tree_new(commit, path)
 
-        assert_equal(impl._svn.info2.call_args[0]
-                     [0], 'file://' + g.tmpdir + '/code/trunk/foo')
+        assert (impl._svn.info2.call_args[0]
+                     [0] == 'file://' + g.tmpdir + '/code/trunk/foo')
         assert lcd_partial.called
 
     def test_last_commit_ids(self):
@@ -73,9 +73,9 @@ class TestSVNImplementation:
         commit._id = '5057636b9c1040636b81e4b1:6'
         entries = impl.last_commit_ids(commit, [path])
 
-        assert_equal(entries, {path.strip('/'): '5057636b9c1040636b81e4b1:1'})
-        assert_equal(impl._svn.info2.call_args[0]
-                     [0], 'file://' + g.tmpdir + '/code/trunk')
+        assert entries == {path.strip('/'): '5057636b9c1040636b81e4b1:1'}
+        assert (impl._svn.info2.call_args[0]
+                     [0] == 'file://' + g.tmpdir + '/code/trunk')
 
     @patch('forgesvn.model.svn.svn_path_exists')
     def test__tarball_path_clean(self, path_exists):
@@ -85,16 +85,16 @@ class TestSVNImplementation:
         impl = SVNImplementation(repo)
         path_exists.return_value = False
         # edge cases
-        assert_equal(impl._tarball_path_clean(None), '')
-        assert_equal(impl._tarball_path_clean(''), '')
+        assert impl._tarball_path_clean(None) == ''
+        assert impl._tarball_path_clean('') == ''
         # common
-        assert_equal(impl._tarball_path_clean('/some/path/'), 'some/path')
-        assert_equal(impl._tarball_path_clean('some/path'), 'some/path')
-        assert_equal(impl._tarball_path_clean('/some/path/tags/1.0/some/dir'), 'some/path/tags/1.0/some/dir')
+        assert impl._tarball_path_clean('/some/path/') == 'some/path'
+        assert impl._tarball_path_clean('some/path') == 'some/path'
+        assert impl._tarball_path_clean('/some/path/tags/1.0/some/dir') == 'some/path/tags/1.0/some/dir'
         # with fallback to trunk
         path_exists.return_value = True
-        assert_equal(impl._tarball_path_clean(None), 'trunk')
-        assert_equal(impl._tarball_path_clean(''), 'trunk')
+        assert impl._tarball_path_clean(None) == 'trunk'
+        assert impl._tarball_path_clean('') == 'trunk'
 
     @patch('forgesvn.model.svn.svn_path_exists')
     def test_update_checkout_url(self, svn_path_exists):
@@ -104,14 +104,14 @@ class TestSVNImplementation:
         svn_path_exists.side_effect = lambda path: False
         opts['checkout_url'] = 'invalid'
         impl.update_checkout_url()
-        assert_equal(opts['checkout_url'], '')
+        assert opts['checkout_url'] == ''
 
         svn_path_exists.side_effect = lambda path: path.endswith('trunk')
         opts['checkout_url'] = 'invalid'
         impl.update_checkout_url()
-        assert_equal(opts['checkout_url'], 'trunk')
+        assert opts['checkout_url'] == 'trunk'
 
         svn_path_exists.side_effect = lambda path: path.endswith('trunk')
         opts['checkout_url'] = ''
         impl.update_checkout_url()
-        assert_equal(opts['checkout_url'], 'trunk')
+        assert opts['checkout_url'] == 'trunk'
diff --git a/ForgeSVN/forgesvn/tests/test_svn_app.py b/ForgeSVN/forgesvn/tests/test_svn_app.py
index b62a5cf5b..605ffe59c 100644
--- a/ForgeSVN/forgesvn/tests/test_svn_app.py
+++ b/ForgeSVN/forgesvn/tests/test_svn_app.py
@@ -40,8 +40,8 @@ class TestSVNApp(unittest.TestCase):
         ThreadLocalORMSession.close_all()
 
     def test_admin_menu(self):
-        assert_equals(len(c.app.admin_menu()), 7)
-        assert_equals(c.app.admin_menu()[0].label, 'Checkout URL')
+        assert len(c.app.admin_menu()) == 7
+        assert c.app.admin_menu()[0].label == 'Checkout URL'
 
     def test_uninstall(self):
         from allura import model as M
diff --git a/ForgeSVN/forgesvn/tests/test_tasks.py b/ForgeSVN/forgesvn/tests/test_tasks.py
index 3fa2c6d7c..e95899ecf 100644
--- a/ForgeSVN/forgesvn/tests/test_tasks.py
+++ b/ForgeSVN/forgesvn/tests/test_tasks.py
@@ -57,7 +57,7 @@ class TestRepoTasks(unittest.TestCase):
             repo_tasks.init()
             M.main_orm_session.flush()
             assert f.called_with()
-            assert_equal(ns, M.Notification.query.find().count())
+            assert ns == M.Notification.query.find().count()
 
     def test_clone(self):
         ns = M.Notification.query.find().count()
diff --git a/ForgeShortUrl/forgeshorturl/tests/functional/test.py b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
index 704dcc78f..547ca8e01 100644
--- a/ForgeShortUrl/forgeshorturl/tests/functional/test.py
+++ b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
@@ -43,7 +43,7 @@ class TestRootController(TestController):
         response.form['full_url'] = 'http://www.google.com/'
         response.form.submit()
         redir = self.app.get('/url/test', status=302)
-        assert_equal(redir.location, 'http://www.google.com/')
+        assert redir.location == 'http://www.google.com/'
 
     def test_shorturl_http_head(self):
         response = self.app.get('/admin/url/add')
@@ -51,7 +51,7 @@ class TestRootController(TestController):
         response.form['full_url'] = 'http://www.google.com/'
         response.form.submit()
         r = self.app.head('/url/test', status=302)
-        assert_equal(r.location, 'http://www.google.com/')
+        assert r.location == 'http://www.google.com/'
 
     def test_shorturl_update(self):
         response = self.app.get('/admin/url/add')
@@ -59,7 +59,7 @@ class TestRootController(TestController):
         response.form['full_url'] = 'http://www.google.com/'
         response.form.submit()
         redir = self.app.get('/url/g', status=302)
-        assert_equal(redir.location, 'http://www.google.com/')
+        assert redir.location == 'http://www.google.com/'
 
         response = self.app.get('/url/')
         form = response.forms['short-url-form']
@@ -69,7 +69,7 @@ class TestRootController(TestController):
         form.action = '/admin/url/add/'
         form.submit()
         redir = self.app.get('/url/g', status=302)
-        assert_equal(redir.location, 'http://www.yahoo.com/')
+        assert redir.location == 'http://www.yahoo.com/'
 
     def test_shorturl_not_found(self):
         self.app.post('/admin/url/add',
@@ -148,7 +148,7 @@ class TestRootController(TestController):
 
             url = ShortUrl.build_short_url(app, 's')
 
-            assert_equal(url, 'b:n:p:m:s')
+            assert url == 'b:n:p:m:s'
 
     def test_short_url(self):
         response = self.app.get('/admin/url/add')
@@ -162,4 +162,4 @@ class TestRootController(TestController):
                 'short_url.url_pattern': '{base_url}:{nbhd}:{project}:{mount_point}:{short_name}',
                 'base_url': 'b',
         }):
-            assert_equal(surl.short_url(), 'b:p:test:url:test')
+            assert surl.short_url() == 'b:p:test:url:test'
diff --git a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
index 7c82519a1..9074e46ff 100644
--- a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
+++ b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
@@ -70,18 +70,18 @@ def test_fix_discussion():
     tracker = M.AppConfig.query.find({'options.mount_point': 'bugs'}).first()
     t1 = TM.Ticket.query.get(ticket_num=1)
     t2 = TM.Ticket.query.get(ticket_num=2)
-    assert_not_equal(
-        t1.discussion_thread.discussion.app_config_id, tracker._id)
-    assert_not_equal(t2.discussion_thread.discussion_id, tracker.discussion_id)
+    assert (
+        t1.discussion_thread.discussion.app_config_id != tracker._id)
+    assert t2.discussion_thread.discussion_id != tracker.discussion_id
 
     cmd = fix_discussion.FixDiscussion('fix-discussion')
     cmd.run([test_config, 'test'])
 
     t1 = TM.Ticket.query.get(ticket_num=1)
     t2 = TM.Ticket.query.get(ticket_num=2)
-    assert_equal(t1.discussion_thread.discussion.app_config_id, tracker._id)
-    assert_equal(t2.discussion_thread.discussion_id, tracker.discussion_id)
+    assert t1.discussion_thread.discussion.app_config_id == tracker._id
+    assert t2.discussion_thread.discussion_id == tracker.discussion_id
     for p in t2.discussion_thread.posts:
-        assert_equal(p.app_config_id, tracker._id)
-        assert_equal(p.app_id, tracker._id)
-        assert_equal(p.discussion_id, tracker.discussion_id)
+        assert p.app_config_id == tracker._id
+        assert p.app_id == tracker._id
+        assert p.discussion_id == tracker.discussion_id
diff --git a/ForgeTracker/forgetracker/tests/functional/test_rest.py b/ForgeTracker/forgetracker/tests/functional/test_rest.py
index 0d1f4acc3..be72dd250 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -90,13 +90,13 @@ class TestRestNewTicket(TestTrackerApiBase):
             summary = 'Second ticket'
             self.create_ticket(summary=summary)
             t = TM.Ticket.query.get(summary=summary)
-            assert_not_equal(t, None)
+            assert t != None
         # Set rate limit to 1 in first hour of project
         with h.push_config(config, **{'forgetracker.rate_limits': '{"3600": 1}'}):
             summary = 'Third ticket'
             self.create_ticket(summary=summary, status=429)
             t = TM.Ticket.query.get(summary=summary)
-            assert_equal(t, None)
+            assert t == None
 
 
 class TestRestUpdateTicket(TestTrackerApiBase):
@@ -152,7 +152,7 @@ class TestRestIndex(TestTrackerApiBase):
         # make sure it didn't get removed from the db too
         ticket_config = M.AppConfig.query.get(
             project_id=c.project._id, tool_name='tickets')
-        assert_equal(ticket_config.options.get('TicketMonitoringEmail'),
+        assert (ticket_config.options.get('TicketMonitoringEmail') ==
                      'test@localhost')
 
     @td.with_tool('test', 'Tickets', 'dummy')
@@ -164,7 +164,7 @@ class TestRestIndex(TestTrackerApiBase):
             params={'tracker': str(dummy_tracker.config._id)}).follow()
 
         ticket = self.api_get('/rest/p/test/bugs/1/')
-        assert_equal(ticket.request.path, '/rest/p/test/dummy/1/')
+        assert ticket.request.path == '/rest/p/test/dummy/1/'
 
 
 class TestRestDiscussion(TestTrackerApiBase):
@@ -206,11 +206,11 @@ class TestRestSearch(TestTrackerApiBase):
     def test_no_criteria(self, paged_search):
         paged_search.return_value = dict(tickets=[self.ticket])
         r = self.api_get('/rest/p/test/bugs/search')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['tickets'][0]['summary'], 'our test ticket')
-        assert_equal(r.json['tickets'][0]['ticket_num'], 5)
-        assert_equal(r.json['tickets'][0]['status'], 'open')
-        assert_equal(r.json['tickets'][0]['labels'], ['tiny', 'minor'])
+        assert r.status_int == 200
+        assert r.json['tickets'][0]['summary'] == 'our test ticket'
+        assert r.json['tickets'][0]['ticket_num'] == 5
+        assert r.json['tickets'][0]['status'] == 'open'
+        assert r.json['tickets'][0]['labels'] == ['tiny', 'minor']
         assert 'description' not in r.json
         assert 'discussion_thread' not in r.json
 
@@ -227,16 +227,16 @@ class TestRestSearch(TestTrackerApiBase):
         )
         r = self.api_get('/rest/p/test/bugs/search',
                          q=q, sort='status', limit='2')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['limit'], 2)
-        assert_equal(r.json['q'], q)
-        assert_equal(r.json['sort'], 'status')
-        assert_equal(r.json['count'], 1)
-        assert_equal(r.json['page'], 0)
-        assert_equal(r.json['tickets'][0]['summary'], 'our test ticket')
-        assert_equal(r.json['tickets'][0]['ticket_num'], 5)
-        assert_equal(r.json['tickets'][0]['status'], 'open')
-        assert_equal(r.json['tickets'][0]['labels'], ['tiny', 'minor'])
+        assert r.status_int == 200
+        assert r.json['limit'] == 2
+        assert r.json['q'] == q
+        assert r.json['sort'] == 'status'
+        assert r.json['count'] == 1
+        assert r.json['page'] == 0
+        assert r.json['tickets'][0]['summary'] == 'our test ticket'
+        assert r.json['tickets'][0]['ticket_num'] == 5
+        assert r.json['tickets'][0]['status'] == 'open'
+        assert r.json['tickets'][0]['labels'] == ['tiny', 'minor']
         assert 'description' not in r.json
         assert 'discussion_thread' not in r.json
 
@@ -253,13 +253,13 @@ class TestRestHasAccess(TestTrackerApiBase):
         r = self.api_get(
             '/rest/p/test/bugs/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/bugs/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -275,10 +275,10 @@ class TestRestHasAccess(TestTrackerApiBase):
         r = self.api_get(
             '/rest/p/test/bugs/has_access?user=test-admin&perm=delete',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/bugs/has_access?user=test-user&perm=delete',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 02ff29132..e0556322e 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -303,9 +303,9 @@ class TestFunctionalController(TrackerTestController):
     def test_new_ticket(self):
         summary = 'test new ticket'
         ticket_view = self.new_ticket(summary=summary).follow()
-        assert_true(summary in ticket_view)
+        assert summary in ticket_view
         opts = self.subscription_options(ticket_view)
-        assert_equal(opts['subscribed'], False)
+        assert opts['subscribed'] == False
 
     def test_ticket_get_markdown(self):
         self.new_ticket(summary='my ticket', description='my description')
@@ -350,17 +350,17 @@ class TestFunctionalController(TrackerTestController):
                 {'name': '1.0', 'count': 2},
                 {'name': '2.0', 'count': 0}
             ]}
-        assert_equal(r.text, json.dumps(counts))
+        assert r.text == json.dumps(counts)
         # Private tickets shouldn't be included in counts if user doesn't
         # have read access to private tickets.
         r = self.app.get('/bugs/milestone_counts',
                          extra_environ=dict(username='*anonymous'))
         counts['milestone_counts'][0]['count'] = 1
-        assert_equal(r.text, json.dumps(counts))
+        assert r.text == json.dumps(counts)
 
         self.app.post('/bugs/1/delete')
         r = self.app.get('/bugs/milestone_counts')
-        assert_equal(r.text, json.dumps(counts))
+        assert r.text == json.dumps(counts)
 
     def test_bin_counts(self):
         self.new_ticket(summary='test new')
@@ -368,9 +368,9 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
 
         r = self.app.get('/bugs/bin_counts')
-        assert_equal(r.json, {"bin_counts": [{"count": 2, "label": "Changes"},
+        assert r.json == {"bin_counts": [{"count": 2, "label": "Changes"},
                                              {"count": 0, "label": "Closed Tickets"},
-                                             {"count": 2, "label": "Open Tickets"}]})
+                                             {"count": 2, "label": "Open Tickets"}]}
 
         """
         forgetracker.model.ticket.Globals.bin_count doesn't do a permission check like corresponding milestone_count
@@ -409,13 +409,13 @@ class TestFunctionalController(TrackerTestController):
         response = self.app.get('/bugs/new/?summary=very buggy&description=descr&labels=label1,label2&private=true'
                                 '&assigned_to=test-user&_milestone=2.0&status=pending')
         form = self._find_new_ticket_form(response)
-        assert_equal(form['ticket_form.summary'].value, 'very buggy')
-        assert_equal(form['ticket_form.description'].value, 'descr')
-        assert_equal(form['ticket_form.labels'].value, 'label1,label2')
-        assert_equal(form['ticket_form.assigned_to'].value, 'test-user')
-        assert_equal(form['ticket_form._milestone'].value, '2.0')
-        assert_equal(form['ticket_form.status'].value, 'pending')
-        assert_equal(form['ticket_form.private'].checked, True)
+        assert form['ticket_form.summary'].value == 'very buggy'
+        assert form['ticket_form.description'].value == 'descr'
+        assert form['ticket_form.labels'].value == 'label1,label2'
+        assert form['ticket_form.assigned_to'].value == 'test-user'
+        assert form['ticket_form._milestone'].value == '2.0'
+        assert form['ticket_form.status'].value == 'pending'
+        assert form['ticket_form.private'].checked == True
 
     def test_mass_edit(self):
         self.new_ticket(summary='First Ticket').follow()
@@ -481,9 +481,9 @@ class TestFunctionalController(TrackerTestController):
         ticket1 = tm.Ticket.query.get(summary='Ticket1')
         ticket2 = tm.Ticket.query.get(summary='Ticket2')
         ticket3 = tm.Ticket.query.get(summary='Ticket3')
-        assert_equal(ticket1.labels, ['tag2', 'tag3'])
-        assert_equal(ticket2.labels, ['tag1', 'tag2', 'tag3'])
-        assert_equal(ticket3.labels, ['tag1', 'tag2', 'tag3'])
+        assert ticket1.labels == ['tag2', 'tag3']
+        assert ticket2.labels == ['tag1', 'tag2', 'tag3']
+        assert ticket3.labels == ['tag1', 'tag2', 'tag3']
         r = self.app.get('/p/test/bugs/3/')
         assert '<li><strong>Labels</strong>: tag1, tag2 --&gt; tag1, tag2, tag3</li>' in r
 
@@ -524,8 +524,8 @@ class TestFunctionalController(TrackerTestController):
             'summary': 'First Custom'}).first()
         ticket2 = tm.Ticket.query.find({
             'summary': 'Second Custom'}).first()
-        assert_equal(ticket1.custom_fields._major, False)
-        assert_equal(ticket2.custom_fields._major, False)
+        assert ticket1.custom_fields._major == False
+        assert ticket2.custom_fields._major == False
 
         self.app.post('/p/test/bugs/update_tickets', {
             '__search': '',
@@ -542,8 +542,8 @@ class TestFunctionalController(TrackerTestController):
         assert '<li><strong>Major</strong>: False --&gt; True</li>' in r
         ticket1 = tm.Ticket.query.find({'summary': 'First Custom'}).first()
         ticket2 = tm.Ticket.query.find({'summary': 'Second Custom'}).first()
-        assert_equal(ticket1.custom_fields._major, True)
-        assert_equal(ticket2.custom_fields._major, True)
+        assert ticket1.custom_fields._major == True
+        assert ticket2.custom_fields._major == True
 
         self.app.post('/p/test/bugs/update_tickets', {
             '__search': '',
@@ -554,7 +554,7 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ticket2 = tm.Ticket.query.find({
             'summary': 'Second Custom'}).first()
-        assert_equal(ticket2.custom_fields._major, False)
+        assert ticket2.custom_fields._major == False
         self.app.post('/p/test/bugs/update_tickets', {
             '__search': '',
             '__ticket_ids': (
@@ -566,8 +566,8 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ticket1 = tm.Ticket.query.find({'summary': 'First Custom'}).first()
         ticket2 = tm.Ticket.query.find({'summary': 'Second Custom'}).first()
-        assert_equal(ticket1.custom_fields._major, True)
-        assert_equal(ticket2.custom_fields._major, False)
+        assert ticket1.custom_fields._major == True
+        assert ticket2.custom_fields._major == False
 
     def test_mass_edit_select_options_split(self):
         params = dict(
@@ -585,12 +585,12 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/edit/')
         opts = r.html.find('select', attrs={'name': '_type'})
         opts = opts.findAll('option')
-        assert_equal(opts[0].get('value'), '')
-        assert_equal(opts[0].getText(), 'no change')
-        assert_equal(opts[1].get('value'), 'Bug')
-        assert_equal(opts[1].getText(), 'Bug')
-        assert_equal(opts[2].get('value'), 'Feature Request')
-        assert_equal(opts[2].getText(), 'Feature Request')
+        assert opts[0].get('value') == ''
+        assert opts[0].getText() == 'no change'
+        assert opts[1].get('value') == 'Bug'
+        assert opts[1].getText() == 'Bug'
+        assert opts[2].get('value') == 'Feature Request'
+        assert opts[2].getText() == 'Feature Request'
 
     def test_mass_edit_private_field(self):
         kw = {'private': True}
@@ -613,8 +613,8 @@ class TestFunctionalController(TrackerTestController):
         assert '<li><strong>Private</strong>: No --&gt; Yes</li>' not in r
         ticket1 = tm.Ticket.query.find({'summary': 'First'}).first()
         ticket2 = tm.Ticket.query.find({'summary': 'Second'}).first()
-        assert_equal(ticket1.private, False)
-        assert_equal(ticket2.private, False)
+        assert ticket1.private == False
+        assert ticket2.private == False
 
         self.app.post('/p/test/bugs/update_tickets', {
             '__search': '',
@@ -630,8 +630,8 @@ class TestFunctionalController(TrackerTestController):
         assert '<li><strong>Private</strong>: No --&gt; Yes</li>' in r
         ticket1 = tm.Ticket.query.find({'summary': 'First'}).first()
         ticket2 = tm.Ticket.query.find({'summary': 'Second'}).first()
-        assert_equal(ticket1.private, True)
-        assert_equal(ticket2.private, True)
+        assert ticket1.private == True
+        assert ticket2.private == True
 
         ticket2.private = False
         self.app.post('/p/test/bugs/update_tickets', {
@@ -644,15 +644,15 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ticket1 = tm.Ticket.query.find({'summary': 'First'}).first()
         ticket2 = tm.Ticket.query.find({'summary': 'Second'}).first()
-        assert_equal(ticket1.private, True)
-        assert_equal(ticket2.private, False)
+        assert ticket1.private == True
+        assert ticket2.private == False
 
     def test_private_ticket(self):
         ticket_view = self.new_ticket(summary='Public Ticket').follow()
-        assert_in('<label class="simple">Private:</label> No', squish_spaces(ticket_view.text))
+        assert '<label class="simple">Private:</label> No' in squish_spaces(ticket_view.text)
         ticket_view = self.new_ticket(summary='Private Ticket',
                                       private=True).follow()
-        assert_in('<label class="simple">Private:</label> Yes', squish_spaces(ticket_view.text))
+        assert '<label class="simple">Private:</label> Yes' in squish_spaces(ticket_view.text)
         M.MonQTask.run_ready()
         # Creator sees private ticket on list page...
         index_response = self.app.get('/p/test/bugs/')
@@ -699,12 +699,12 @@ class TestFunctionalController(TrackerTestController):
             'ticket_form.private': 'on',
         })
         response = self.app.get('/bugs/1/')
-        assert_true('<li><strong>private</strong>: No --&gt; Yes</li>' in response)
+        assert '<li><strong>private</strong>: No --&gt; Yes</li>' in response
 
     def test_discussion_disabled_ticket(self):
         response = self.new_ticket(summary='test discussion disabled ticket').follow()
         # New tickets will not show discussion disabled
-        assert_not_in('<span class="closed">Discussion Disabled</span>', response)
+        assert '<span class="closed">Discussion Disabled</span>' not in response
 
         ticket_params = {
             'ticket_form.summary': 'test discussion disabled ticket',
@@ -719,28 +719,28 @@ class TestFunctionalController(TrackerTestController):
 
         # Disable Discussion
         response = self.app.post('/bugs/1/update_ticket_from_widget', ticket_params).follow()
-        assert_in('<li><strong>discussion</strong>: enabled --&gt; disabled</li>', response)
-        assert_in('<span class="closed">Discussion Disabled</span>', response)
-        assert_in('edit_post_form reply', response)  # Make sure admin can still comment
+        assert '<li><strong>discussion</strong>: enabled --&gt; disabled</li>' in response
+        assert '<span class="closed">Discussion Disabled</span>' in response
+        assert 'edit_post_form reply' in response  # Make sure admin can still comment
 
         # Unauthorized user cannot comment or even see form fields
         env = dict(username='*anonymous')
         r = self.app.get('/p/test/bugs/1', extra_environ=env)
-        assert_not_in('edit_post_form reply', r)
+        assert 'edit_post_form reply' not in r
 
         # Test re-enabling discussions
         ticket_params['ticket_form.discussion_disabled'] = 'off'
         response = self.app.post('/bugs/1/update_ticket_from_widget', ticket_params).follow()
-        assert_in('<li><strong>discussion</strong>: disabled --&gt; enabled</li>', response)
-        assert_not_in('<span class="closed">Discussion Disabled</span>', response)
+        assert '<li><strong>discussion</strong>: disabled --&gt; enabled</li>' in response
+        assert '<span class="closed">Discussion Disabled</span>' not in response
 
         # Test solr search
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
         # At this point, there is one ticket and it has discussion_disabled set to False
         r = self.app.get('/bugs/search/?q=discussion_disabled_b:False')
-        assert_in('1 results', r)
-        assert_in('test discussion disabled ticket', r)
+        assert '1 results' in r
+        assert 'test discussion disabled ticket' in r
 
         # Set discussion_disabled to True and search again
         ticket_params['ticket_form.discussion_disabled'] = 'on'
@@ -748,12 +748,12 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
         r = self.app.get('/bugs/search/?q=discussion_disabled_b:True')
-        assert_in('1 results', r)
-        assert_in('test discussion disabled ticket', r)
+        assert '1 results' in r
+        assert 'test discussion disabled ticket' in r
 
         # Make sure there are no other tickets or false positives for good measure.
         r = self.app.get('/bugs/search/?q=discussion_disabled_b:False')
-        assert_in('0 results', r)
+        assert '0 results' in r
 
     @td.with_tool('test', 'Tickets', 'doc-bugs')
     def test_two_trackers(self):
@@ -763,13 +763,13 @@ class TestFunctionalController(TrackerTestController):
         ThreadLocalORMSession.flush_all()
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
-        assert_true(summary in ticket_view)
+        assert summary in ticket_view
         index_view = self.app.get('/doc-bugs/')
-        assert_true(summary in index_view)
-        assert_true(sidebar_contains(index_view, '<span>1.0</span>'))
+        assert summary in index_view
+        assert sidebar_contains(index_view, '<span>1.0</span>')
         index_view = self.app.get('/bugs/')
-        assert_true(sidebar_contains(index_view, '<span>1.0</span>'))
-        assert_false(summary in index_view)
+        assert sidebar_contains(index_view, '<span>1.0</span>')
+        assert not summary in index_view
 
     def test_render_ticket(self):
         summary = 'test render ticket'
@@ -790,7 +790,7 @@ class TestFunctionalController(TrackerTestController):
         # Make sure the 'Create Ticket' button is disabled for user without 'create' perm
         r = self.app.get('/bugs/', extra_environ=dict(username='*anonymous'))
         create_button = r.html.find('a', attrs={'href': '/p/test/bugs/new/'})
-        assert_equal(create_button['class'], ['icon', 'sidebar-disabled'])
+        assert create_button['class'] == ['icon', 'sidebar-disabled']
 
     @patch.dict('allura.lib.app_globals.config', markdown_cache_threshold='0')
     def test_cached_convert(self):
@@ -811,11 +811,11 @@ class TestFunctionalController(TrackerTestController):
         # We want to make sure the 'last_updated' field isn't updated by the cache creation
         r = self.app.get('/bugs/1').follow()
         last_updated = r.html.find("span", {"id": "updated_id"}).text.strip()
-        assert_equal(last_updated, '2010-01-01')
+        assert last_updated == '2010-01-01'
 
         # Make sure the cache has been saved.
         t = tm.Ticket.query.find({'_id': ticket._id}).first()
-        assert_in('<h1 id="test-markdown-cached_convert">Test markdown cached_convert</h1>', t.description_cache.html)
+        assert '<h1 id="test-markdown-cached_convert">Test markdown cached_convert</h1>' in t.description_cache.html
 
     def test_ticket_diffs(self):
         self.new_ticket(summary='difftest', description='1\n2\n3\n')
@@ -834,8 +834,8 @@ class TestFunctionalController(TrackerTestController):
             'comment': 'user comment',
         })
         t = tm.Ticket.query.get(ticket_num=1)
-        assert_true(t.discussion_thread.first_post.is_meta)
-        assert_false(t.discussion_thread.last_post.is_meta)
+        assert t.discussion_thread.first_post.is_meta
+        assert not t.discussion_thread.last_post.is_meta
 
     def test_ticket_label_unlabel(self):
         summary = 'test labeling and unlabeling a ticket'
@@ -850,9 +850,9 @@ class TestFunctionalController(TrackerTestController):
             'comment': ''
         })
         response = self.app.get('/bugs/1/')
-        assert_true('yellow' in response)
-        assert_true('greén' in response)
-        assert_true('<li><strong>labels</strong>:  --&gt; yellow, greén</li>' in response)
+        assert 'yellow' in response
+        assert 'greén' in response
+        assert '<li><strong>labels</strong>:  --&gt; yellow, greén</li>' in response
         self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz',
             'description': 'bbb',
@@ -863,8 +863,8 @@ class TestFunctionalController(TrackerTestController):
             'comment': ''
         })
         response = self.app.get('/bugs/1/')
-        assert_true('yellow' in response)
-        assert_true('<li><strong>labels</strong>: yellow, greén --&gt; yellow</li>' in response)
+        assert 'yellow' in response
+        assert '<li><strong>labels</strong>: yellow, greén --&gt; yellow</li>' in response
         self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz',
             'description': 'bbb',
@@ -875,7 +875,7 @@ class TestFunctionalController(TrackerTestController):
             'comment': ''
         })
         response = self.app.get('/bugs/1/')
-        assert_true('<li><strong>labels</strong>: yellow --&gt; </li>' in response)
+        assert '<li><strong>labels</strong>: yellow --&gt; </li>' in response
 
     def test_new_attachment(self):
         file_name = 'test_root.py'
@@ -885,12 +885,12 @@ class TestFunctionalController(TrackerTestController):
         ticket_editor = self.app.post('/bugs/1/update_ticket', {
             'summary': 'zzz'
         }, upload_files=[upload]).follow()
-        assert_true(file_name in ticket_editor)
+        assert file_name in ticket_editor
         assert '<span>py</span>' not in ticket_editor
         ticket_page = self.app.get('/bugs/1/')
         diff = ticket_page.html.findAll('div', attrs={'class': 'codehilite'})
         added = diff[-1].findAll('span', attrs={'class': 'gi'})[-1]
-        assert_in('+test_root.py', added.getText())
+        assert '+test_root.py' in added.getText()
 
     def test_delete_attachment(self):
         file_name = 'test_root.py'
@@ -904,7 +904,7 @@ class TestFunctionalController(TrackerTestController):
         req = self.app.get('/bugs/1/')
         form = self._find_update_ticket_form(req)
         file_link = BeautifulSoup(form.text).findAll('a')[2]
-        assert_equal(file_link.string, file_name)
+        assert file_link.string == file_name
         self.app.post(str(file_link['href']), {
             'delete': 'True'
         })
@@ -912,7 +912,7 @@ class TestFunctionalController(TrackerTestController):
         assert '/p/test/bugs/1/attachment/test_root.py' not in ticket_page
         diff = ticket_page.html.findAll('div', attrs={'class': 'codehilite'})
         removed = diff[-1].findAll('span', attrs={'class': 'gd'})[-1]
-        assert_in('-test_root.py', removed.getText())
+        assert '-test_root.py' in removed.getText()
 
     def test_delete_attachment_from_comments(self):
         ticket_view = self.new_ticket(summary='test ticket').follow()
@@ -947,7 +947,7 @@ class TestFunctionalController(TrackerTestController):
         }, upload_files=[upload]).follow()
         form = self._find_update_ticket_form(ticket_editor)
         download = self.app.get(str(BeautifulSoup(form.text).findAll('a')[2]['href']))
-        assert_equal(download.body, file_data)
+        assert download.body == file_data
 
     def test_two_attachments(self):
         file_name1 = 'test_root1.py'
@@ -1043,12 +1043,12 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
         r = self.app.get('/p/test/bugs/3/')
-        assert_in('Tickets: #1', r)
-        assert_not_in('Tickets: <s>#1</s>', r)
-        assert_in('Tickets: <s>#2</s>', r)
+        assert 'Tickets: #1' in r
+        assert 'Tickets: <s>#1</s>' not in r
+        assert 'Tickets: <s>#2</s>' in r
 
-        assert_in('<a class="alink" href="/p/test/bugs/1/">[#1]</a>', r.text)
-        assert_in('<a class="alink strikethrough" href="/p/test/bugs/2/">[#2]</a>', r.text)
+        assert '<a class="alink" href="/p/test/bugs/1/">[#1]</a>' in r.text
+        assert '<a class="alink strikethrough" href="/p/test/bugs/2/">[#2]</a>' in r.text
 
     def test_ticket_view_editable(self):
         summary = 'test ticket view page can be edited'
@@ -1299,22 +1299,22 @@ class TestFunctionalController(TrackerTestController):
         form['ticket_form.custom_fields._category'] = 'bugs'
         error_form = form.submit()
         form = self._find_new_ticket_form(error_form)
-        assert_equal(form['ticket_form.custom_fields._priority'].value, 'urgent')
-        assert_equal(form['ticket_form.custom_fields._category'].value, 'bugs')
+        assert form['ticket_form.custom_fields._priority'].value == 'urgent'
+        assert form['ticket_form.custom_fields._category'].value == 'bugs'
         # Test edit ticket form
         self.new_ticket(summary='Test ticket')
         response = self.app.get('/bugs/1/')
         form = self._find_update_ticket_form(response)
-        assert_equal(
-            form['ticket_form.custom_fields._priority'].value, 'normal')
-        assert_equal(form['ticket_form.custom_fields._category'].value, '')
+        assert (
+            form['ticket_form.custom_fields._priority'].value == 'normal')
+        assert form['ticket_form.custom_fields._category'].value == ''
         form['ticket_form.summary'] = ''
         form['ticket_form.custom_fields._priority'] = 'urgent'
         form['ticket_form.custom_fields._category'] = 'bugs'
         error_form = form.submit()
         form = self._find_update_ticket_form(error_form)
-        assert_equal(form['ticket_form.custom_fields._priority'].value, 'urgent')
-        assert_equal(form['ticket_form.custom_fields._category'].value, 'bugs')
+        assert form['ticket_form.custom_fields._priority'].value == 'urgent'
+        assert form['ticket_form.custom_fields._category'].value == 'bugs'
 
     def test_new_ticket_validation(self):
         summary = 'ticket summary'
@@ -1384,9 +1384,9 @@ class TestFunctionalController(TrackerTestController):
         response.mustcontain('results of 3')
         response.mustcontain('test second ticket')
         next_page_link = response.html.select('.page_list a')[0]
-        assert_equal(next_page_link.text, '2')
+        assert next_page_link.text == '2'
         # keep 'q' and zero-based page nums:
-        assert_equal(next_page_link['href'], '/p/test/bugs/search/?q=test&limit=2&page=1')
+        assert next_page_link['href'] == '/p/test/bugs/search/?q=test&limit=2&page=1'
 
         # 'filter' is special kwarg, don't let it cause problems
         r = self.app.get('/p/test/bugs/search/?q=test&filter=blah')
@@ -1550,8 +1550,8 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.post(f['action'], params=params,
                           headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='1'))
-        assert_true(post_content in r)
-        assert_true(len(r.html.findAll(attrs={'class': 'discussion-post'})) == 1)
+        assert post_content in r
+        assert len(r.html.findAll(attrs={'class': 'discussion-post'})) == 1
 
         new_summary = 'old ticket'
         for f in ticket_view.html.findAll('form'):
@@ -1566,8 +1566,8 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.post(f['action'], params=params,
                           headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='1'))
-        assert_true(summary + ' --&gt; ' + new_summary in r)
-        assert_true(len(r.html.findAll(attrs={'class': 'discussion-post meta_post'})) == 1)
+        assert summary + ' --&gt; ' + new_summary in r
+        assert len(r.html.findAll(attrs={'class': 'discussion-post meta_post'})) == 1
 
     def test_discussion_paging(self):
         summary = 'test discussion paging'
@@ -1585,17 +1585,17 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.post(f['action'], params=params,
                           headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='-1'))
-        assert_true(summary in r)
+        assert summary in r
         r = self.app.get('/bugs/1/', dict(page='1'))
-        assert_true(post_content in r)
+        assert post_content in r
         # no pager if just one page
-        assert_false('Page 1 of 1' in r)
+        assert not 'Page 1 of 1' in r
         # add some more posts and check for pager
         for i in range(2):
             r = self.app.post(f['action'], params=params,
                               headers={'Referer': b'/bugs/1/'})
         r = self.app.get('/bugs/1/', dict(page='1', limit='2'))
-        assert_true('Page 2 of 2' in r)
+        assert 'Page 2 of 2' in r
 
     def test_discussion_feed(self):
         summary = 'test discussion paging'
@@ -1643,16 +1643,16 @@ class TestFunctionalController(TrackerTestController):
         ThreadLocalORMSession.flush_all()
         response = self.app.get('/p/test/bugs/?sort=summary+asc')
         ticket_rows = response.html.find('table', {'class': 'ticket-list'}).find('tbody')
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
         edit_link = response.html.find('a', {'title': 'Bulk Edit'})
         expected_link = "/p/test/bugs/edit/?q=%21status%3Aclosed+%26%26+%21status%3Awont-fix"\
                         "&sort=snippet_s+asc&limit=25&filter=&page=0"
         assert_equivalent_urls(expected_link, edit_link['href'])
         response = self.app.get(edit_link['href'])
         ticket_rows = response.html.find('tbody', {'class': 'ticket-list'})
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
 
     def test_bulk_edit_milestone(self):
         self.new_ticket(summary='test first ticket',
@@ -1666,17 +1666,17 @@ class TestFunctionalController(TrackerTestController):
         ThreadLocalORMSession.flush_all()
         response = self.app.get('/p/test/bugs/milestone/1.0/?sort=ticket_num+asc')
         ticket_rows = response.html.find('table', {'class': 'ticket-list'}).find('tbody')
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
-        assert_in('test third ticket', ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
+        assert 'test third ticket' in ticket_rows.text
         edit_link = response.html.find('a', {'title': 'Bulk Edit'})
         expected_link = "/p/test/bugs/edit/?q=_milestone%3A1.0&sort=ticket_num_i+asc&limit=25&filter=&page=0"
         assert_equivalent_urls(expected_link, edit_link['href'])
         response = self.app.get(edit_link['href'])
         ticket_rows = response.html.find('tbody', {'class': 'ticket-list'})
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
-        assert_in('test third ticket', ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
+        assert 'test third ticket' in ticket_rows.text
 
     def test_bulk_edit_search(self):
         self.new_ticket(summary='test first ticket', status='open')
@@ -1687,17 +1687,17 @@ class TestFunctionalController(TrackerTestController):
         ThreadLocalORMSession.flush_all()
         response = self.app.get('/p/test/bugs/search/?q=status%3Aopen')
         ticket_rows = response.html.find('table', {'class': 'ticket-list'}).find('tbody')
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
-        assert_false('test third ticket' in ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
+        assert not 'test third ticket' in ticket_rows.text
         edit_link = response.html.find('a', {'title': 'Bulk Edit'})
         expected_link = "/p/test/bugs/edit/?q=status%3Aopen&limit=25&filter=%7B%7D&page=0"
         assert_equivalent_urls(expected_link, edit_link['href'])
         response = self.app.get(edit_link['href'])
         ticket_rows = response.html.find('tbody', {'class': 'ticket-list'})
-        assert_in('test first ticket', ticket_rows.text)
-        assert_in('test second ticket', ticket_rows.text)
-        assert_false('test third ticket' in ticket_rows.text)
+        assert 'test first ticket' in ticket_rows.text
+        assert 'test second ticket' in ticket_rows.text
+        assert not 'test third ticket' in ticket_rows.text
 
     def test_bulk_edit_after_filtering(self):
         self.new_ticket(summary='test first ticket', status='open')
@@ -1713,7 +1713,7 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.post('/bugs/save_ticket', {
             'ticket_form.summary': 'new ticket with attachment'
         }, upload_files=[upload]).follow()
-        assert_in(file_name, r)
+        assert file_name in r
         ThreadLocalORMSession.flush_all()
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
@@ -1724,7 +1724,7 @@ class TestFunctionalController(TrackerTestController):
             '**Attachments:**\n\n'
             '- [tést_root.py]'
             '(http://localhost/p/test/bugs/1/attachment/t%C3%A9st_root.py)')
-        assert_in(expected_text, email.kwargs['text'])
+        assert expected_text in email.kwargs['text']
 
     def test_ticket_notification_contains_milestones(self):
         params = dict(
@@ -1755,8 +1755,8 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         ThreadLocalORMSession.flush_all()
         email = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
-        assert_in('**Releases:** 1.0-beta', email.kwargs.text)
-        assert_in('**Milestone:** 2.0', email.kwargs.text)
+        assert '**Releases:** 1.0-beta' in email.kwargs.text
+        assert '**Milestone:** 2.0' in email.kwargs.text
 
     def test_bulk_edit_notifications(self):
         self.new_ticket(summary='test first ticket',
@@ -1788,26 +1788,26 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
 
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
-        assert_equal(len(emails), 3)
+        assert len(emails) == 3
         for email in emails:
-            assert_equal(email.kwargs.subject, '[test:bugs] Mass edit changes by Test Admin')
+            assert email.kwargs.subject == '[test:bugs] Mass edit changes by Test Admin'
         first_user_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(first_user._id)
         }).all()
-        assert_equal(len(first_user_email), 1)
+        assert len(first_user_email) == 1
         first_user_email = first_user_email[0]
         second_user_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(second_user._id)
         }).all()
-        assert_equal(len(second_user_email), 1)
+        assert len(second_user_email) == 1
         second_user_email = second_user_email[0]
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(admin._id)
         }).all()
-        assert_equal(len(admin_email), 1)
+        assert len(admin_email) == 1
         admin_email = admin_email[0]
 
         # Expected data
@@ -1835,13 +1835,13 @@ class TestFunctionalController(TrackerTestController):
 - **Milestone**: 1.0 --> 2.0
 '''
         email = '\n'.join([email_header, first_ticket_changes, ''])
-        assert_equal(email, first_user_email.kwargs.text)
+        assert email == first_user_email.kwargs.text
         email = '\n'.join([email_header, second_ticket_changes, ''])
-        assert_equal(email, second_user_email.kwargs.text)
-        assert_in(email_header, admin_email.kwargs.text)
-        assert_in(first_ticket_changes, admin_email.kwargs.text)
-        assert_in(second_ticket_changes, admin_email.kwargs.text)
-        assert_in(third_ticket_changes, admin_email.kwargs.text)
+        assert email == second_user_email.kwargs.text
+        assert email_header in admin_email.kwargs.text
+        assert first_ticket_changes in admin_email.kwargs.text
+        assert second_ticket_changes in admin_email.kwargs.text
+        assert third_ticket_changes in admin_email.kwargs.text
 
     def test_bulk_edit_notifications_monitoring_email(self):
         self.app.post('/admin/bugs/set_options', params={
@@ -1862,9 +1862,9 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
         # one for admin and one for monitoring email
-        assert_equal(len(emails), 2)
+        assert len(emails) == 2
         for email in emails:
-            assert_equal(email.kwargs.subject, '[test:bugs] Mass edit changes by Test Admin')
+            assert email.kwargs.subject == '[test:bugs] Mass edit changes by Test Admin'
         admin = M.User.by_username('test-admin')
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
@@ -1874,11 +1874,11 @@ class TestFunctionalController(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 1)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 1
         admin_email_text = admin_email[0].kwargs.text
         monitoring_email_text = monitoring_email[0].kwargs.text
-        assert_equal(admin_email_text, monitoring_email_text)
+        assert admin_email_text == monitoring_email_text
 
     def test_bulk_edit_notifications_monitoring_email_public_only(self):
         """Test that private tickets are not included in bulk edit
@@ -1902,9 +1902,9 @@ class TestFunctionalController(TrackerTestController):
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
         # one for admin and one for monitoring email
-        assert_equal(len(emails), 2)
+        assert len(emails) == 2
         for email in emails:
-            assert_equal(email.kwargs.subject, '[test:bugs] Mass edit changes by Test Admin')
+            assert email.kwargs.subject == '[test:bugs] Mass edit changes by Test Admin'
         admin = M.User.by_username('test-admin')
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
@@ -1914,12 +1914,12 @@ class TestFunctionalController(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 1)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 1
         admin_email_text = admin_email[0].kwargs.text
         monitoring_email_text = monitoring_email[0].kwargs.text
-        assert_in('second ticket', admin_email_text)
-        assert_not_in('second ticket', monitoring_email_text)
+        assert 'second ticket' in admin_email_text
+        assert 'second ticket' not in monitoring_email_text
 
     def test_bulk_edit_monitoring_email_all_private_edits(self):
         """Test that no monitoring email is sent if the "public only"
@@ -1942,9 +1942,9 @@ class TestFunctionalController(TrackerTestController):
             'status': 'accepted'})
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
-        assert_equal(len(emails), 1)  # only admin email sent
+        assert len(emails) == 1  # only admin email sent
         for email in emails:
-            assert_equal(email.kwargs.subject, '[test:bugs] Mass edit changes by Test Admin')
+            assert email.kwargs.subject == '[test:bugs] Mass edit changes by Test Admin'
         admin = M.User.by_username('test-admin')
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
@@ -1954,8 +1954,8 @@ class TestFunctionalController(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 0)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 0
 
     def test_filtered_by_subscription(self):
         self.new_ticket(summary='test first ticket', status='open')
@@ -1991,50 +1991,50 @@ class TestFunctionalController(TrackerTestController):
         }
         filtered_changes = c.app.globals.filtered_by_subscription(changes)
         filtered_users = [uid for uid, data in filtered_changes.items()]
-        assert_equal(sorted(filtered_users),
+        assert (sorted(filtered_users) ==
                      sorted(u._id for u in users[:-1] + [admin]))
         ticket_ids = [t._id for t in tickets]
-        assert_equal(filtered_changes[users[0]._id], set(ticket_ids[0:1]))
-        assert_equal(filtered_changes[users[1]._id], set(ticket_ids[:-1]))
-        assert_equal(filtered_changes[admin._id], set(ticket_ids[:-1]))
+        assert filtered_changes[users[0]._id] == set(ticket_ids[0:1])
+        assert filtered_changes[users[1]._id] == set(ticket_ids[:-1])
+        assert filtered_changes[admin._id] == set(ticket_ids[:-1])
 
     def test_vote(self):
         r = self.new_ticket(summary='test vote').follow()
-        assert_true(r.html.find('div', {'id': 'vote'}))
+        assert r.html.find('div', {'id': 'vote'})
 
         # test vote form not visible to anon user
         r = self.app.get('/bugs/1/', extra_environ=dict(username='*anonymous'))
-        assert_false(r.html.find('div', {'id': 'vote'}))
+        assert not r.html.find('div', {'id': 'vote'})
 
         r = self.app.get('/bugs/1/')
         votes_up = r.html.find('span', {'class': 'votes-up'})
         votes_down = r.html.find('span', {'class': 'votes-down'})
-        assert_in('0', str(votes_up))
-        assert_in('0', str(votes_down))
+        assert '0' in str(votes_up)
+        assert '0' in str(votes_down)
 
         # invalid vote
         r = self.app.post('/bugs/1/vote', dict(vote='invalid'))
         expected_resp = json.dumps(dict(status='error', votes_up=0, votes_down=0, votes_percent=0))
-        assert_equal(r.response.text, expected_resp)
+        assert r.response.text == expected_resp
 
         # vote up
         r = self.app.post('/bugs/1/vote', dict(vote='u'))
         expected_resp = json.dumps(dict(status='ok', votes_up=1, votes_down=0, votes_percent=100))
-        assert_equal(r.response.text, expected_resp)
+        assert r.response.text == expected_resp
 
         # vote down by another user
         r = self.app.post('/bugs/1/vote', dict(vote='d'),
                           extra_environ=dict(username='test-user-0'))
 
         expected_resp = json.dumps(dict(status='ok', votes_up=1, votes_down=1, votes_percent=50))
-        assert_equal(r.response.text, expected_resp)
+        assert r.response.text == expected_resp
 
         # make sure that on the page we see the same result
         r = self.app.get('/bugs/1/')
         votes_up = r.html.find('span', {'class': 'votes-up'})
         votes_down = r.html.find('span', {'class': 'votes-down'})
-        assert_in('1', str(votes_up))
-        assert_in('1', str(votes_down))
+        assert '1' in str(votes_up)
+        assert '1' in str(votes_down)
 
         r = self.app.get('/bugs/')
         assert "Votes" in r
@@ -2075,7 +2075,7 @@ class TestFunctionalController(TrackerTestController):
         ticket_url = r.headers['Location']
         r = self.app.get(ticket_url, extra_environ=dict(username='*anonymous'))
         a = r.html.find('a', {'class': 'icon edit_ticket'})
-        assert_equal(a.text, '\xa0Edit')
+        assert a.text == '\xa0Edit'
 
     def test_ticket_creator_cant_edit_private_ticket_without_update_perm(self):
         p = M.Project.query.get(shortname='test')
@@ -2184,18 +2184,18 @@ class TestFunctionalController(TrackerTestController):
         tracker = p.app_instance('bugs2')
         r = self.app.post('/p/test/bugs/1/move/',
                           params={'tracker': str(tracker.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test2/bugs2/1/')
+        assert r.request.path == '/p/test2/bugs2/1/'
         summary = r.html.findAll('h2', {'class': 'dark title'})[0].find('span').contents[0].strip()
-        assert_equal(summary, '#1 test')
+        assert summary == '#1 test'
         ac_id = tracker.config._id
         ticket = tm.Ticket.query.find({
             'app_config_id': ac_id,
             'ticket_num': 1}).first()
         assert ticket is not None, "Can't find moved ticket"
-        assert_equal(ticket.discussion_thread.app_config_id, ac_id)
-        assert_equal(ticket.discussion_thread.discussion.app_config_id, ac_id)
+        assert ticket.discussion_thread.app_config_id == ac_id
+        assert ticket.discussion_thread.discussion.app_config_id == ac_id
         post = ticket.discussion_thread.last_post
-        assert_equal(post.text, 'Ticket moved from /p/test/bugs/1/')
+        assert post.text == 'Ticket moved from /p/test/bugs/1/'
 
     @td.with_tool('test2', 'Tickets', 'bugs2')
     def test_move_ticket_feed(self):
@@ -2211,7 +2211,7 @@ class TestFunctionalController(TrackerTestController):
         post = ticket.discussion_thread.last_post
         ticket_link = '/p/test2/bugs2/1/?limit=25#' + post.slug
         msg = 'Ticket moved from /p/test/bugs/1/'
-        assert_equal(post.text, msg)
+        assert post.text == msg
         # auto comment content and link to it should be in a ticket's feed
         r = self.app.get('/p/test2/bugs2/1/feed')
         assert msg in r, r
@@ -2236,9 +2236,9 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.post(f['action'], params=params,
                           headers={'Referer': b'/p/test2/bugs2/1/'})
         r = self.app.get('/p/test2/bugs2/1/', dict(page='1'))
-        assert_true(post_content in r)
+        assert post_content in r
         comments_cnt = len(r.html.findAll(attrs={'class': 'discussion-post'}))
-        assert_equal(comments_cnt, 2)  # moved auto comment + new comment
+        assert comments_cnt == 2  # moved auto comment + new comment
         post = ticket.discussion_thread.last_post
         # content and link to the ticket should be in a tracker's feed
         ticket_link = '/p/test2/bugs2/1/?limit=25#' + post.slug
@@ -2284,11 +2284,11 @@ class TestFunctionalController(TrackerTestController):
         dummy_tracker = p.app_instance('dummy')
         r = self.app.post('/p/test/bugs/1/move',
                           params={'tracker': str(dummy_tracker.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test/dummy/1/')
+        assert r.request.path == '/p/test/dummy/1/'
 
         # test that old url redirects to moved ticket
         self.app.get('/p/test/bugs/1/', status=301).follow()
-        assert_equal(r.request.path, '/p/test/dummy/1/')
+        assert r.request.path == '/p/test/dummy/1/'
 
     @td.with_tool('test', 'Tickets', 'dummy')
     def test_move_ticket_and_delete_tool(self):
@@ -2304,7 +2304,7 @@ class TestFunctionalController(TrackerTestController):
         dummy_tracker = p.app_instance('dummy')
         r = self.app.post('/p/test/bugs/1/move',
                           params={'tracker': str(dummy_tracker.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test/dummy/1/')
+        assert r.request.path == '/p/test/dummy/1/'
 
         # delete 'dummy' tracker
         p.uninstall_app('dummy')
@@ -2329,7 +2329,7 @@ class TestFunctionalController(TrackerTestController):
         dummy_tracker = p.app_instance('dummy')
         r = self.app.post('/p/test/bugs/1/move',
                           params={'tracker': str(dummy_tracker.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test/dummy/1/')
+        assert r.request.path == '/p/test/dummy/1/'
 
         # comment ticket 2
         M.Notification.query.remove()
@@ -2346,8 +2346,8 @@ class TestFunctionalController(TrackerTestController):
         # notification for ticket 2 should reference [test:bugs], not
         # [test:dummy]
         n = M.Notification.query.find().all()[0]
-        assert_in('[test:bugs]', n.subject)
-        assert_in('[test:bugs]', n.reply_to_address)
+        assert '[test:bugs]' in n.subject
+        assert '[test:bugs]' in n.reply_to_address
 
     @td.with_tool('test2', 'Tickets', 'features')
     def test_move_ticket_subscriptions(self):
@@ -2380,7 +2380,7 @@ class TestFunctionalController(TrackerTestController):
         # move ticket to new project & tool: test/bugs/2 => test2/features/1
         r = self.app.post('/p/test/bugs/2/move',
                           params={'tracker': str(features.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test2/features/1/')
+        assert r.request.path == '/p/test2/features/1/'
 
         # test-user should be subscribed to it
         assert M.Mailbox.query.get(user_id=user._id,
@@ -2425,16 +2425,16 @@ class TestFunctionalController(TrackerTestController):
         attach_comments = r.html.findAll('div', attrs={'class': 'attachment_item'})
         ta = str(attach_tickets)  # ticket's attachments
         ca = str(attach_comments)  # comment's attachments
-        assert_in('<a href="/p/test2/bugs2/1/attachment/neo-icon-set-454545-256x350.png"', ta)
-        assert_in('<img alt="Thumbnail" src="/p/test2/bugs2/1/attachment/neo-icon-set-454545-256x350.png/thumb"', ta)
+        assert '<a href="/p/test2/bugs2/1/attachment/neo-icon-set-454545-256x350.png"' in ta
+        assert '<img alt="Thumbnail" src="/p/test2/bugs2/1/attachment/neo-icon-set-454545-256x350.png/thumb"' in ta
         p = M.Post.query.find().sort('timestamp', 1).first()
-        assert_in(
+        assert (
             '<a href="/p/test2/bugs2/_discuss/thread/%s/%s/attachment/test.txt"' %
-            (p.thread_id, p.slug), ca)
+            (p.thread_id, p.slug) in ca)
         for attach in M.BaseAttachment.query.find():
-            assert_equal(attach.app_config_id, bugs2.config._id)
+            assert attach.app_config_id == bugs2.config._id
             if attach.attachment_type == 'DiscussionAttachment':
-                assert_equal(attach.discussion_id, bugs2.config.discussion_id)
+                assert attach.discussion_id == bugs2.config.discussion_id
 
     @td.with_tool('test', 'Tickets', 'dummy')
     def test_move_ticket_comments(self):
@@ -2450,14 +2450,14 @@ class TestFunctionalController(TrackerTestController):
         form.fields[field_name][0].value = 'I am comment'
         form.submit()
         r = self.app.get('/p/test/bugs/1/')
-        assert_in('I am comment', r)
+        assert 'I am comment' in r
 
         p = M.Project.query.get(shortname='test')
         dummy_tracker = p.app_instance('dummy')
         r = self.app.post('/p/test/bugs/1/move',
                           params={'tracker': str(dummy_tracker.config._id)}).follow()
-        assert_equal(r.request.path, '/p/test/dummy/1/')
-        assert_in('I am comment', r)
+        assert r.request.path == '/p/test/dummy/1/'
+        assert 'I am comment' in r
 
     def test_tags(self):
         p = M.Project.query.get(shortname='test')
@@ -2468,9 +2468,9 @@ class TestFunctionalController(TrackerTestController):
         # Testing only empty 'term', because mim doesn't support aggregation
         # calls
         r = self.app.get('/p/test/bugs/tags')
-        assert_equal(json.loads(r.text), [])
+        assert json.loads(r.text) == []
         r = self.app.get('/p/test/bugs/tags?term=')
-        assert_equal(json.loads(r.text), [])
+        assert json.loads(r.text) == []
 
     def test_rest_tickets(self):
         ticket_view = self.new_ticket(summary='test').follow()
@@ -2493,12 +2493,12 @@ class TestFunctionalController(TrackerTestController):
         discussion_url = r.html.findAll('form')[-1]['action'][:-4]
         r = self.app.get('/rest/p/test/bugs/1/')
         r = json.loads(r.text)
-        assert_equal(r['ticket']['discussion_thread_url'],
+        assert (r['ticket']['discussion_thread_url'] ==
                      'http://localhost/rest%s' % discussion_url)
         slug = r['ticket']['discussion_thread']['posts'][0]['slug']
-        assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['url'],
+        assert (r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['url'] ==
                      f'http://localhost{discussion_url}{slug}/attachment/test.txt')
-        assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['bytes'],
+        assert (r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['bytes'] ==
                      11)
 
         file_name = 'test_root.py'
@@ -2509,7 +2509,7 @@ class TestFunctionalController(TrackerTestController):
         }, upload_files=[upload]).follow()
         r = self.app.get('/rest/p/test/bugs/1/')
         r = json.loads(r.text)
-        assert_equal(r['ticket']['attachments'][0]['url'],
+        assert (r['ticket']['attachments'][0]['url'] ==
                      'http://localhost/p/test/bugs/1/attachment/test_root.py')
 
     def test_html_escaping(self):
@@ -2521,7 +2521,7 @@ class TestFunctionalController(TrackerTestController):
             ThreadLocalORMSession.flush_all()
             email = M.MonQTask.query.find(
                 dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
-            assert_equal(email.kwargs.subject,
+            assert (email.kwargs.subject ==
                          '[test:bugs] #1 test <h2> ticket')
             text = email.kwargs.text
             assert '** [bugs:#1] test &lt;h2&gt; ticket**' in text
@@ -2532,17 +2532,17 @@ class TestFunctionalController(TrackerTestController):
                 reply_to=g.noreply,
                 subject=email.kwargs.subject,
                 message_id=h.gen_message_id())
-            assert_equal(_client.sendmail.call_count, 1)
+            assert _client.sendmail.call_count == 1
             return_path, rcpts, body = _client.sendmail.call_args[0]
             body = body.split('\n')
             # check subject
             assert 'Subject: [test:bugs] #1 test <h2> ticket' in body
             # check html, need tags escaped
-            assert_in('<p><strong> <a class="alink" href="http://localhost/p/test/bugs/1/">[bugs:#1]</a>'
-                      ' test &lt;h2&gt; ticket</strong></p>',
+            assert ('<p><strong> <a class="alink" href="http://localhost/p/test/bugs/1/">[bugs:#1]</a>'
+                      ' test &lt;h2&gt; ticket</strong></p>' in
                       body)
             # check plaintext (ok to have "html" tags)
-            assert_in('** [bugs:#1] test <h2> ticket**', body)
+            assert '** [bugs:#1] test <h2> ticket**' in body
 
     @patch('forgetracker.search.query_filter_choices', autospec=True)
     def test_multiselect(self, query_filter_choices):
@@ -2558,16 +2558,16 @@ class TestFunctionalController(TrackerTestController):
         # Set rate limit to unlimit
         with h.push_config(config, **{'forgetracker.rate_limits': '{}'}):
             r = self.app.get('/bugs/new/')
-            assert_equal(r.status_int, 200)
+            assert r.status_int == 200
         # Set rate limit to 1 in first hour of project
         with h.push_config(config, **{'forgetracker.rate_limits': '{"3600": 1}'}):
             r = self.app.get('/bugs/new/')
-            assert_equal(r.status_int, 302)
-            assert_equal(r.location, 'http://localhost/bugs/')
+            assert r.status_int == 302
+            assert r.location == 'http://localhost/bugs/'
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(
-                wf['message'],
+            assert wf['status'] == 'error'
+            assert (
+                wf['message'] ==
                 'Ticket creation rate limit exceeded. Please try again later.')
 
     def test_rate_limit_save_ticket(self):
@@ -2576,24 +2576,24 @@ class TestFunctionalController(TrackerTestController):
             summary = 'Ticket w/o limit'
             post_data = {'ticket_form.summary': summary}
             r = self.app.post('/bugs/save_ticket', post_data).follow()
-            assert_in(summary, r)
+            assert summary in r
             t = tm.Ticket.query.get(summary=summary)
-            assert_not_equal(t, None)
+            assert t != None
         # Set rate limit to 1 in first hour of project
         with h.push_config(config, **{'forgetracker.rate_limits': '{"3600": 1}'}):
             summary = 'Ticket with limit'
             post_data = {'ticket_form.summary': summary}
             r = self.app.post('/bugs/save_ticket', post_data)
-            assert_equal(r.status_int, 302)
-            assert_equal(r.location, 'http://localhost/bugs/')
+            assert r.status_int == 302
+            assert r.location == 'http://localhost/bugs/'
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(
-                wf['message'],
+            assert wf['status'] == 'error'
+            assert (
+                wf['message'] ==
                 'Ticket creation rate limit exceeded. Please try again later.')
-            assert_not_in(summary, r.follow())
+            assert summary not in r.follow()
             t = tm.Ticket.query.get(summary=summary)
-            assert_equal(t, None)
+            assert t == None
 
     def test_user_missing(self):
         # add test-user to project so it can be assigned the ticket
@@ -2904,7 +2904,7 @@ class TestCustomUserField(TrackerTestController):
         kw = {'custom_fields._code_review': ''}
         ticket_view = self.new_ticket(summary='test custom fields', **kw).follow()
         # summary header shows 'nobody'
-        assert_equal(squish_spaces(ticket_view.html.findAll('label', 'simple', text='Code Review:')[0].parent.text),
+        assert (squish_spaces(ticket_view.html.findAll('label', 'simple', text='Code Review:')[0].parent.text) ==
                      ' Code Review: nobody ')
         # form input is blank
         select = ticket_view.html.find('select',
@@ -2919,7 +2919,7 @@ class TestCustomUserField(TrackerTestController):
         kw = {'custom_fields._code_review': 'test-admin'}
         ticket_view = self.new_ticket(summary='test custom fields', **kw).follow()
         # summary header shows 'Test Admin'
-        assert_equal(squish_spaces(ticket_view.html.findAll('label', 'simple', text='Code Review:')[0].parent.text),
+        assert (squish_spaces(ticket_view.html.findAll('label', 'simple', text='Code Review:')[0].parent.text) ==
                      ' Code Review: Test Admin ')
         # form input is blank
         select = ticket_view.html.find('select',
@@ -2928,7 +2928,7 @@ class TestCustomUserField(TrackerTestController):
         for option in select.findChildren():
             if option.has_attr('selected'):
                 selected = option
-        assert_equal(selected['value'], 'test-admin')
+        assert selected['value'] == 'test-admin'
 
     def test_change_user_field(self):
         kw = {'custom_fields._code_review': ''}
@@ -2942,8 +2942,8 @@ class TestCustomUserField(TrackerTestController):
         kw = {'custom_fields._code_review': 'test-admin'}
         self.new_ticket(summary='test custom fields', **kw)
         r = self.app.get('/bugs/')
-        assert_equal(r.html.find('table', 'ticket-list').findAll('th')[7].text.strip()[:11], 'Code Review')
-        assert_equal(r.html.find('table', 'ticket-list').tbody.tr.findAll('td')[7].text, 'Test Admin')
+        assert r.html.find('table', 'ticket-list').findAll('th')[7].text.strip()[:11] == 'Code Review'
+        assert r.html.find('table', 'ticket-list').tbody.tr.findAll('td')[7].text == 'Test Admin'
 
 
 class TestHelpTextOptions(TrackerTestController):
@@ -3041,9 +3041,9 @@ class TestBulkMove(TrackerTestController):
         r = self.app.get('/bugs/move/?q=The')
         tickets_table = r.html.find('tbody', attrs={'class': 'ticket-list'})
         tickets = tickets_table.findAll('tr')
-        assert_equal(len(tickets), 2)
-        assert_in('The Empire Strikes Back', tickets_table.text)
-        assert_in('Return Of The Jedi', tickets_table.text)
+        assert len(tickets) == 2
+        assert 'The Empire Strikes Back' in tickets_table.text
+        assert 'Return Of The Jedi' in tickets_table.text
 
     @td.with_tool('test', 'Tickets', 'bugs2')
     @td.with_tool('test2', 'Tickets', 'bugs')
@@ -3053,7 +3053,7 @@ class TestBulkMove(TrackerTestController):
         trackers = r.html.find('select', {'name': 'tracker'}).findAll('option')
         trackers = {t.text for t in trackers}
         expected = {'test/bugs', 'test/bugs2', 'test2/bugs', 'test2/bugs2'}
-        assert_equal(trackers, expected)
+        assert trackers == expected
         move_btn = r.html.find('input', attrs={'type': 'submit', 'value': 'Move'})
         assert move_btn is not None
 
@@ -3078,16 +3078,16 @@ class TestBulkMove(TrackerTestController):
         original_ac_id = original_tracker.config._id
         moved_tickets = tm.Ticket.query.find({'app_config_id': ac_id}).all()
         original_tickets = tm.Ticket.query.find({'app_config_id': original_ac_id}).all()
-        assert_equal(len(moved_tickets), 2)
-        assert_equal(len(original_tickets), 1)
+        assert len(moved_tickets) == 2
+        assert len(original_tickets) == 1
         for ticket in moved_tickets:
-            assert_equal(ticket.discussion_thread.app_config_id, ac_id)
-            assert_equal(ticket.discussion_thread.discussion.app_config_id, ac_id)
+            assert ticket.discussion_thread.app_config_id == ac_id
+            assert ticket.discussion_thread.discussion.app_config_id == ac_id
             post = ticket.discussion_thread.last_post
-            assert_in('Ticket moved from /p/test/bugs/', post.text)
+            assert 'Ticket moved from /p/test/bugs/' in post.text
         for t in original_tickets:
-            assert_equal(t.discussion_thread.app_config_id, original_ac_id)
-            assert_equal(t.discussion_thread.discussion.app_config_id, original_ac_id)
+            assert t.discussion_thread.app_config_id == original_ac_id
+            assert t.discussion_thread.discussion.app_config_id == original_ac_id
             assert t.discussion_thread.last_post is None
 
     @td.with_tool('test2', 'Tickets', 'bugs2')
@@ -3112,46 +3112,46 @@ class TestBulkMove(TrackerTestController):
         })
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
-        assert_equal(len(emails), 3)
+        assert len(emails) == 3
         for email in emails:
-            assert_equal(email.kwargs.subject,
+            assert (email.kwargs.subject ==
                          '[test:bugs] Mass ticket moving by Test Admin')
         first_user_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(first_user._id)
         }).all()
-        assert_equal(len(first_user_email), 1)
+        assert len(first_user_email) == 1
         first_user_email = first_user_email[0]
         second_user_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(second_user._id)
         }).all()
-        assert_equal(len(second_user_email), 1)
+        assert len(second_user_email) == 1
         second_user_email = second_user_email[0]
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': str(admin._id)
         }).all()
-        assert_equal(len(admin_email), 1)
+        assert len(admin_email) == 1
         admin_email = admin_email[0]
 
         email_header = 'Tickets were moved from [test:bugs] to [test2:bugs2]\n'
         first_ticket_changes = 'A New Hope'
         second_ticket_changes = 'The Empire Strikes Back'
         third_ticket_changes = 'Return Of The Jedi'
-        assert_in(email_header, first_user_email.kwargs.text)
-        assert_in(first_ticket_changes, first_user_email.kwargs.text)
-        assert_in(email_header, second_user_email.kwargs.text)
-        assert_in(second_ticket_changes, second_user_email.kwargs.text)
-        assert_in(email_header, admin_email.kwargs.text)
-        assert_in(first_ticket_changes, admin_email.kwargs.text)
-        assert_in(second_ticket_changes, admin_email.kwargs.text)
-        assert_in(third_ticket_changes, admin_email.kwargs.text)
+        assert email_header in first_user_email.kwargs.text
+        assert first_ticket_changes in first_user_email.kwargs.text
+        assert email_header in second_user_email.kwargs.text
+        assert second_ticket_changes in second_user_email.kwargs.text
+        assert email_header in admin_email.kwargs.text
+        assert first_ticket_changes in admin_email.kwargs.text
+        assert second_ticket_changes in admin_email.kwargs.text
+        assert third_ticket_changes in admin_email.kwargs.text
         # After tickets moved, user should see a flash
         mbox = M.Mailbox.query.get(user_id=admin._id, is_flash=True)
         notification_id = mbox.queue[-1]
         notification = M.Notification.query.get(_id=notification_id)
-        assert_equal(notification.text,
+        assert (notification.text ==
                      'Tickets moved from test/bugs to test2/bugs2')
 
     @td.with_tool('test2', 'Tickets', 'bugs2')
@@ -3175,9 +3175,9 @@ class TestBulkMove(TrackerTestController):
         })
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
-        assert_equal(len(emails), 2)
+        assert len(emails) == 2
         for email in emails:
-            assert_equal(email.kwargs.subject,
+            assert (email.kwargs.subject ==
                          '[test:bugs] Mass ticket moving by Test Admin')
         admin_email = M.MonQTask.query.find({
             'task_name': 'allura.tasks.mail_tasks.sendmail',
@@ -3187,21 +3187,21 @@ class TestBulkMove(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 1)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 1
         admin_email_text = admin_email[0].kwargs.text
-        assert_in('test:bugs:#1 --> test2:bugs2:#1 A New Hope',
+        assert ('test:bugs:#1 --> test2:bugs2:#1 A New Hope' in
                   admin_email_text)
-        assert_in('test:bugs:#2 --> test2:bugs2:#2 The Empire Strikes Back',
+        assert ('test:bugs:#2 --> test2:bugs2:#2 The Empire Strikes Back' in
                   admin_email_text)
-        assert_in('test:bugs:#3 --> test2:bugs2:#3 Return Of The Jedi',
+        assert ('test:bugs:#3 --> test2:bugs2:#3 Return Of The Jedi' in
                   admin_email_text)
         monitoring_email_text = monitoring_email[0].kwargs.text
-        assert_in('test:bugs:#1 --> test2:bugs2:#1 A New Hope',
+        assert ('test:bugs:#1 --> test2:bugs2:#1 A New Hope' in
                   monitoring_email_text)
-        assert_in('test:bugs:#2 --> test2:bugs2:#2 The Empire Strikes Back',
+        assert ('test:bugs:#2 --> test2:bugs2:#2 The Empire Strikes Back' in
                   monitoring_email_text)
-        assert_in('test:bugs:#3 --> test2:bugs2:#3 Return Of The Jedi',
+        assert ('test:bugs:#3 --> test2:bugs2:#3 Return Of The Jedi' in
                   monitoring_email_text)
 
     @td.with_tool('test2', 'Tickets', 'bugs2')
@@ -3232,9 +3232,9 @@ class TestBulkMove(TrackerTestController):
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
         # one for admin and one for monitoring email
-        assert_equal(len(emails), 2)
+        assert len(emails) == 2
         for email in emails:
-            assert_equal(email.kwargs.subject,
+            assert (email.kwargs.subject ==
                          '[test:bugs] Mass ticket moving by Test Admin')
         admin = M.User.by_username('test-admin')
         admin_email = M.MonQTask.query.find({
@@ -3245,12 +3245,12 @@ class TestBulkMove(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 1)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 1
         admin_email_text = admin_email[0].kwargs.text
         monitoring_email_text = monitoring_email[0].kwargs.text
-        assert_in('second ticket', admin_email_text)
-        assert_not_in('second ticket', monitoring_email_text)
+        assert 'second ticket' in admin_email_text
+        assert 'second ticket' not in monitoring_email_text
 
     @td.with_tool('test2', 'Tickets', 'bugs2')
     def test_monitoring_email_all_private_moved(self):
@@ -3279,9 +3279,9 @@ class TestBulkMove(TrackerTestController):
         })
         M.MonQTask.run_ready()
         emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
-        assert_equal(len(emails), 1)  # only admin email sent
+        assert len(emails) == 1  # only admin email sent
         for email in emails:
-            assert_equal(email.kwargs.subject,
+            assert (email.kwargs.subject ==
                          '[test:bugs] Mass ticket moving by Test Admin')
         admin = M.User.by_username('test-admin')
         admin_email = M.MonQTask.query.find({
@@ -3292,8 +3292,8 @@ class TestBulkMove(TrackerTestController):
             'task_name': 'allura.tasks.mail_tasks.sendmail',
             'kwargs.destinations': 'monitoring@email.com'
         }).all()
-        assert_equal(len(admin_email), 1)
-        assert_equal(len(monitoring_email), 0)
+        assert len(admin_email) == 1
+        assert len(monitoring_email) == 0
 
 
 def sidebar_contains(response, text):
@@ -3304,7 +3304,7 @@ def sidebar_contains(response, text):
 class TestStats(TrackerTestController):
     def test_stats(self):
         r = self.app.get('/bugs/stats/', status=200)
-        assert_in('# tickets: 0', r.text)
+        assert '# tickets: 0' in r.text
 
 
 class TestNotificationEmailGrouping(TrackerTestController):
@@ -3315,9 +3315,9 @@ class TestNotificationEmailGrouping(TrackerTestController):
         ThreadLocalORMSession.flush_all()
         email = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
         ticket = tm.Ticket.query.get(ticket_num=1)
-        assert_equal(email.kwargs.message_id, ticket.message_id())
-        assert_equal(email.kwargs.in_reply_to, None)
-        assert_equal(email.kwargs.references, [])
+        assert email.kwargs.message_id == ticket.message_id()
+        assert email.kwargs.in_reply_to == None
+        assert email.kwargs.references == []
 
     def test_comments(self):
         ticket_view = self.new_ticket(summary='Test Ticket').follow()
@@ -3336,9 +3336,9 @@ class TestNotificationEmailGrouping(TrackerTestController):
         ticket = tm.Ticket.query.get(ticket_num=1)
         top_level_comment = ticket.discussion_thread.posts[0]
         top_level_comment_msg_id = ticket.url() + top_level_comment._id
-        assert_equal(email.kwargs.message_id, top_level_comment_msg_id)
-        assert_equal(email.kwargs.in_reply_to, ticket.message_id())
-        assert_equal(email.kwargs.references, [ticket.message_id()])
+        assert email.kwargs.message_id == top_level_comment_msg_id
+        assert email.kwargs.in_reply_to == ticket.message_id()
+        assert email.kwargs.references == [ticket.message_id()]
 
         ThreadLocalORMSession.flush_all()
         M.MonQTask.query.remove()
@@ -3356,9 +3356,9 @@ class TestNotificationEmailGrouping(TrackerTestController):
         email = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
         ticket = tm.Ticket.query.get(ticket_num=1)
         reply = [post for post in ticket.discussion_thread.posts if post.text == reply_text][0]
-        assert_equal(email.kwargs.message_id, ticket.url() + reply._id)
-        assert_equal(email.kwargs.in_reply_to, top_level_comment_msg_id)
-        assert_equal(email.kwargs.references,
+        assert email.kwargs.message_id == ticket.url() + reply._id
+        assert email.kwargs.in_reply_to == top_level_comment_msg_id
+        assert (email.kwargs.references ==
                      [ticket.message_id(), top_level_comment_msg_id])
 
 
@@ -3370,10 +3370,10 @@ def test_status_passthru():
                           open_status_names='foo bar', closed_status_names='qux baz')
     ThreadLocalORMSession.flush_all()
     app = c.project.app_instance('tsp')
-    assert_equal(app.globals.set_of_open_status_names, {'foo', 'bar'})
-    assert_equal(app.globals.set_of_closed_status_names, {'qux', 'baz'})
-    assert_not_in('open_status_names', app.config.options)
-    assert_not_in('closed_status_names', app.config.options)
+    assert app.globals.set_of_open_status_names == {'foo', 'bar'}
+    assert app.globals.set_of_closed_status_names == {'qux', 'baz'}
+    assert 'open_status_names' not in app.config.options
+    assert 'closed_status_names' not in app.config.options
 
 
 class TestArtifactLinks(TrackerTestController):
@@ -3393,15 +3393,15 @@ class TestArtifactLinks(TrackerTestController):
         self.new_ticket('/features/', summary='Ticket 1 in features', _milestone='1.0').follow()
         ticket_bugs = tm.Ticket.query.get(summary='Ticket 1 in bugs')
         ticket_features = tm.Ticket.query.get(summary='Ticket 1 in features')
-        assert_equal(ticket_bugs.ticket_num, 1)
-        assert_equal(ticket_bugs.app.config._id, bugs.config._id)
-        assert_equal(ticket_features.ticket_num, 1)
-        assert_equal(ticket_features.app.config._id, features.config._id)
+        assert ticket_bugs.ticket_num == 1
+        assert ticket_bugs.app.config._id == bugs.config._id
+        assert ticket_features.ticket_num == 1
+        assert ticket_features.app.config._id == features.config._id
 
         c.app = bugs
         link = '<div class="markdown_content"><p><a class="alink" href="/p/test/bugs/1/">[#1]</a></p></div>'
-        assert_equal(g.markdown.convert('[#1]'), link)
+        assert g.markdown.convert('[#1]') == link
 
         c.app = features
         link = '<div class="markdown_content"><p><a class="alink" href="/p/test/features/1/">[#1]</a></p></div>'
-        assert_equal(g.markdown.convert('[#1]'), link)
+        assert g.markdown.convert('[#1]') == link
diff --git a/ForgeTracker/forgetracker/tests/test_app.py b/ForgeTracker/forgetracker/tests/test_app.py
index b67bdb969..aed0fb60b 100644
--- a/ForgeTracker/forgetracker/tests/test_app.py
+++ b/ForgeTracker/forgetracker/tests/test_app.py
@@ -33,7 +33,7 @@ from allura.tests import decorators as td
 from forgetracker import model as TM
 from forgetracker.site_stats import tickets_stats_24hr
 from forgetracker.tests.functional.test_root import TrackerTestController
-from allura.tests.pytest_helpers import with_nose_compatibility
+from alluratest.pytest_helpers import with_nose_compatibility
 
 
 class TestApp:
@@ -54,7 +54,7 @@ class TestApp:
         c.app.handle_message('1', msg)
         # message gets added as a post on the ticket
         post = M.Post.query.get(_id=message_id)
-        assert_equal(post["text"], message)
+        assert post["text"] == message
 
     @td.with_tracker
     def test_inbound_email_no_match(self):
@@ -66,7 +66,7 @@ class TestApp:
         c.app.handle_message('6789', msg)
         # no new message
         post = M.Post.query.get(_id=message_id)
-        assert_equal(post, None)
+        assert post == None
 
     @td.with_tracker
     def test_uninstall(self):
@@ -83,22 +83,22 @@ class TestApp:
         # invoked normally via entry point
         TM.Ticket.new()
         TM.Ticket.new()
-        assert_equal(2, tickets_stats_24hr())
+        assert 2 == tickets_stats_24hr()
 
     @td.with_tracker
     def test_sitemap_xml(self):
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         TM.Ticket.new()
-        assert_equal(1, len(c.app.sitemap_xml()))
+        assert 1 == len(c.app.sitemap_xml())
 
     @td.with_tracker
     def test_sitemap_xml_ignored(self):
         TM.Ticket.new(form_fields=dict(deleted=True))
-        assert_equal([], c.app.sitemap_xml())
+        assert [] == c.app.sitemap_xml()
         # still add to sitemap even if only tickets are closed
         TM.Ticket.new(form_fields=dict(
             status=c.app.globals.closed_status_names[0]))
-        assert_equal(1, len(c.app.sitemap_xml()))
+        assert 1 == len(c.app.sitemap_xml())
 
 
 class TestBulkExport(TrackerTestController):
@@ -132,26 +132,26 @@ class TestBulkExport(TrackerTestController):
 
         tickets = sorted(tracker['tickets'],
                          key=operator.itemgetter('summary'))
-        assert_equal(len(tickets), 2)
+        assert len(tickets) == 2
         ticket_foo = tickets[1]
-        assert_equal(ticket_foo['summary'], 'foo')
-        assert_equal(ticket_foo['custom_fields']['_milestone'], '1.0')
+        assert ticket_foo['summary'] == 'foo'
+        assert ticket_foo['custom_fields']['_milestone'] == '1.0'
         posts_foo = ticket_foo['discussion_thread']['posts']
-        assert_equal(len(posts_foo), 1)
-        assert_equal(posts_foo[0]['text'], 'silly comment')
+        assert len(posts_foo) == 1
+        assert posts_foo[0]['text'] == 'silly comment'
 
         tracker_config = tracker['tracker_config']
-        assert_true('options' in list(tracker_config.keys()))
-        assert_equal(tracker_config['options']['mount_point'], 'bugs')
+        assert 'options' in list(tracker_config.keys())
+        assert tracker_config['options']['mount_point'] == 'bugs'
 
         milestones = sorted(tracker['milestones'],
                             key=operator.itemgetter('name'))
-        assert_equal(milestones[0]['name'], '1.0')
-        assert_equal(milestones[1]['name'], '2.0')
+        assert milestones[0]['name'] == '1.0'
+        assert milestones[1]['name'] == '2.0'
 
         saved_bins_summaries = [bin['summary']
                                 for bin in tracker['saved_bins']]
-        assert_true('Closed Tickets' in saved_bins_summaries)
+        assert 'Closed Tickets' in saved_bins_summaries
 
     def test_export_with_attachments(self):
 
@@ -169,5 +169,5 @@ class TestBulkExport(TrackerTestController):
             self.post.slug,
             'test_file'
         )
-        assert_equal(tickets[1]['discussion_thread']['posts'][0]['attachments'][0]['path'], file_path)
+        assert tickets[1]['discussion_thread']['posts'][0]['attachments'][0]['path'] == file_path
         os.path.exists(file_path)
diff --git a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
index 439e8a5ac..6c063c8f8 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
@@ -43,14 +43,14 @@ class TestGlobalsModel(TrackerTestWithModel):
 
     def test_next_ticket_number_increments(self):
         gl = Globals()
-        assert_equal(gl.next_ticket_num(), 1)
-        assert_equal(gl.next_ticket_num(), 2)
+        assert gl.next_ticket_num() == 1
+        assert gl.next_ticket_num() == 2
 
     def test_ticket_numbers_are_independent(self):
         with h.push_context('test', 'doc-bugs', neighborhood='Projects'):
-            assert_equal(c.app.globals.next_ticket_num(), 1)
+            assert c.app.globals.next_ticket_num() == 1
         with h.push_context('test', 'bugs', neighborhood='Projects'):
-            assert_equal(c.app.globals.next_ticket_num(), 1)
+            assert c.app.globals.next_ticket_num() == 1
 
     @mock.patch('forgetracker.model.ticket.datetime')
     def test_bin_count(self, mock_dt):
@@ -65,14 +65,14 @@ class TestGlobalsModel(TrackerTestWithModel):
         gbl.invalidate_bin_counts.reset_mock()
         gbl._bin_counts_expire = now + timedelta(minutes=5)
         bin = gbl.bin_count('bar')
-        assert_equal(bin['hits'], 2)
+        assert bin['hits'] == 2
         assert not gbl.invalidate_bin_counts.called
 
         # expired, returns value for missing bin
         gbl.invalidate_bin_counts.reset_mock()
         gbl._bin_counts_expire = now - timedelta(minutes=5)
         bin = gbl.bin_count('qux')
-        assert_equal(bin['hits'], 0)
+        assert bin['hits'] == 0
         assert gbl.invalidate_bin_counts.called
 
         # config set to no expiration
@@ -86,7 +86,7 @@ class TestGlobalsModel(TrackerTestWithModel):
         gbl.invalidate_bin_counts.reset_mock()
         gbl._bin_counts_expire = None
         bin = gbl.bin_count('qux')
-        assert_equal(bin['hits'], 0)
+        assert bin['hits'] == 0
         assert gbl.invalidate_bin_counts.called
 
     @mock.patch('forgetracker.tasks.update_bin_counts')
@@ -105,14 +105,14 @@ class TestGlobalsModel(TrackerTestWithModel):
         gbl._bin_counts_invalidated = now - timedelta(minutes=6)
         gbl.invalidate_bin_counts()
         assert mock_task.post.called
-        assert_equal(gbl._bin_counts_invalidated, now)
+        assert gbl._bin_counts_invalidated == now
 
         # never invalidated
         mock_task.reset_mock()
         gbl._bin_counts_invalidated = None
         gbl.invalidate_bin_counts()
         assert mock_task.post.called
-        assert_equal(gbl._bin_counts_invalidated, now)
+        assert gbl._bin_counts_invalidated == now
 
     @mock.patch('forgetracker.model.ticket.Bin')
     @mock.patch('forgetracker.model.ticket.search_artifact')
@@ -126,24 +126,24 @@ class TestGlobalsModel(TrackerTestWithModel):
             mock.Mock(summary='foo', terms='bar')]
         mock_search().hits = 5
 
-        assert_equal(gbl._bin_counts_data, [])  # sanity pre-check
+        assert gbl._bin_counts_data == []  # sanity pre-check
         gbl.update_bin_counts()
         assert mock_bin.query.find.called
         mock_search.assert_called_with(
             forgetracker.model.Ticket, 'bar', rows=0, short_timeout=False, fq=['-deleted_b:true'])
-        assert_equal(gbl._bin_counts_data, [{'summary': 'foo', 'hits': 5}])
-        assert_equal(gbl._bin_counts_expire, now + timedelta(minutes=60))
-        assert_equal(gbl._bin_counts_invalidated, None)
+        assert gbl._bin_counts_data == [{'summary': 'foo', 'hits': 5}]
+        assert gbl._bin_counts_expire == now + timedelta(minutes=60)
+        assert gbl._bin_counts_invalidated == None
 
     def test_append_new_labels(self):
         gbl = Globals()
-        assert_equal(gbl.append_new_labels([], ['tag1']), ['tag1'])
-        assert_equal(
-            gbl.append_new_labels(['tag1', 'tag2'], ['tag2']), ['tag1', 'tag2'])
-        assert_equal(gbl.append_new_labels(
-            ['tag1', 'tag2'], ['tag3']), ['tag1', 'tag2', 'tag3'])
-        assert_equal(gbl.append_new_labels(
-            ['tag1', 'tag2', 'tag3'], ['tag2']), ['tag1', 'tag2', 'tag3'])
+        assert gbl.append_new_labels([], ['tag1']) == ['tag1']
+        assert (
+            gbl.append_new_labels(['tag1', 'tag2'], ['tag2']) == ['tag1', 'tag2'])
+        assert gbl.append_new_labels(
+            ['tag1', 'tag2'], ['tag3']) == ['tag1', 'tag2', 'tag3']
+        assert gbl.append_new_labels(
+            ['tag1', 'tag2', 'tag3'], ['tag2']) == ['tag1', 'tag2', 'tag3']
 
 
 class TestCustomFields(TrackerTestWithModel):
diff --git a/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py b/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
index f22f13eee..3bc0edd50 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_milestone_controller.py
@@ -41,4 +41,4 @@ def test_unicode_lookup():
         mc = MilestoneController(root, field, milestone_urlparam)
 
     assert mc.milestone  # check that it is found
-    assert_equal(mc.milestone.name, 'Перспектива')
+    assert mc.milestone.name == 'Перспектива'
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index ac65449a1..8051cde32 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -49,7 +49,7 @@ class TestWhenSearchingWithCustomFields(WithUserAndBugsApp):
         expected = [dict(sortable_name='_iteration_number_s',
                          name='_iteration_number',
                          label='Iteration Number')]
-        assert_equal(self.response['sortable_custom_fields'], expected)
+        assert self.response['sortable_custom_fields'] == expected
 
     def test_that_tickets_are_listed(self):
         assert self.response['tickets'][0].summary == 'colors are wrong'
diff --git a/ForgeTracker/forgetracker/tests/unit/test_search.py b/ForgeTracker/forgetracker/tests/unit/test_search.py
index 9f34a03ad..c9bb4bdbf 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_search.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_search.py
@@ -35,7 +35,7 @@ def hit_mock():
 
 def test_get_facets():
     hit,expected = hit_mock()
-    assert_equal(get_facets(hit), expected)
+    assert get_facets(hit) == expected
 
 
 @mock.patch('forgetracker.search.search')
@@ -56,4 +56,4 @@ def test_query_filter_choices(c, search):
               'facet.sort': 'index',
               'facet.mincount': 1}
     search.assert_called_once_with(None, **params)
-    assert_equal(result, expected)
+    assert result == expected
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
index c958094db..02744756b 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -91,27 +91,27 @@ class TestTicketModel(TrackerTestWithModel):
 
     def test_activity_extras(self):
         t = Ticket(summary='my ticket', ticket_num=12)
-        assert_in('allura_id', t.activity_extras)
-        assert_equal(t.activity_extras['summary'], t.summary)
+        assert 'allura_id' in t.activity_extras
+        assert t.activity_extras['summary'] == t.summary
 
     def test_has_activity_access(self):
         t = Ticket(summary='ticket', ticket_num=666)
-        assert_true(t.has_activity_access('read', c.user, 'activity'))
+        assert t.has_activity_access('read', c.user, 'activity')
         t.deleted = True
-        assert_false(t.has_activity_access('read', c.user, 'activity'))
+        assert not t.has_activity_access('read', c.user, 'activity')
 
     def test_comment_has_activity_access(self):
         t = Ticket(summary='ticket', ticket_num=666, deleted=True)
         p = t.discussion_thread.add_post(text='test post')
-        assert_equal(p.status, 'ok')
-        assert_true(p.has_activity_access('read', c.user, 'activity'))
+        assert p.status == 'ok'
+        assert p.has_activity_access('read', c.user, 'activity')
         p.status = 'spam'
-        assert_false(p.has_activity_access('read', c.user, 'activity'))
+        assert not p.has_activity_access('read', c.user, 'activity')
         p.status = 'pending'
-        assert_false(p.has_activity_access('read', c.user, 'activity'))
+        assert not p.has_activity_access('read', c.user, 'activity')
         p.status = 'ok'
         p.deleted = True
-        assert_false(p.has_activity_access('read', c.user, 'activity'))
+        assert not p.has_activity_access('read', c.user, 'activity')
 
     def test_private_ticket(self):
         from allura.model import ProjectRole
@@ -138,7 +138,7 @@ class TestTicketModel(TrackerTestWithModel):
         cred = Credentials.get().clear()
 
         t.private = True
-        assert_equal(t.acl, [
+        assert t.acl == [
             ACE.allow(role_developer, 'create'),
             ACE.allow(role_developer, 'delete'),
             ACE.allow(role_developer, 'moderate'),
@@ -151,7 +151,7 @@ class TestTicketModel(TrackerTestWithModel):
             ACE.allow(role_creator, 'post'),
             ACE.allow(role_creator, 'read'),
             ACE.allow(role_creator, 'unmoderated_post'),
-            DENY_ALL])
+            DENY_ALL]
         assert has_access(t, 'read', user=admin)()
         assert has_access(t, 'create', user=admin)()
         assert has_access(t, 'update', user=admin)()
@@ -192,15 +192,15 @@ class TestTicketModel(TrackerTestWithModel):
             summary='test ticket',
             description='test description',
             created_date=datetime(2012, 10, 29, 9, 57, 21, 465000))
-        assert_equal(t.created_date, datetime(2012, 10, 29, 9, 57, 21, 465000))
+        assert t.created_date == datetime(2012, 10, 29, 9, 57, 21, 465000)
         f = Feed.post(
             t,
             title=t.summary,
             description=t.description,
             pubdate=t.created_date)
-        assert_equal(f.pubdate, datetime(2012, 10, 29, 9, 57, 21, 465000))
-        assert_equal(f.title, 'test ticket')
-        assert_equal(f.description,
+        assert f.pubdate == datetime(2012, 10, 29, 9, 57, 21, 465000)
+        assert f.title == 'test ticket'
+        assert (f.description ==
                      '<div class="markdown_content"><p>test description</p></div>')
 
     @td.with_tool('test', 'Tickets', 'bugs', username='test-user')
@@ -215,33 +215,33 @@ class TestTicketModel(TrackerTestWithModel):
             ticket.assigned_to_id = User.by_username('test-user')._id
             ticket.discussion_thread.add_post(text='test comment')
 
-        assert_equal(
-            Ticket.query.find({'app_config_id': app1.config._id}).count(), 1)
-        assert_equal(
-            Ticket.query.find({'app_config_id': app2.config._id}).count(), 0)
-        assert_equal(
-            Post.query.find(dict(thread_id=ticket.discussion_thread._id)).count(), 1)
+        assert (
+            Ticket.query.find({'app_config_id': app1.config._id}).count() == 1)
+        assert (
+            Ticket.query.find({'app_config_id': app2.config._id}).count() == 0)
+        assert (
+            Post.query.find(dict(thread_id=ticket.discussion_thread._id)).count() == 1)
 
         t = ticket.move(app2.config)
-        assert_equal(
-            Ticket.query.find({'app_config_id': app1.config._id}).count(), 0)
-        assert_equal(
-            Ticket.query.find({'app_config_id': app2.config._id}).count(), 1)
-        assert_equal(t.summary, 'test ticket')
-        assert_equal(t.description, 'test description')
-        assert_equal(t.assigned_to.username, 'test-user')
-        assert_equal(t.url(), '/p/test/bugs2/1/')
+        assert (
+            Ticket.query.find({'app_config_id': app1.config._id}).count() == 0)
+        assert (
+            Ticket.query.find({'app_config_id': app2.config._id}).count() == 1)
+        assert t.summary == 'test ticket'
+        assert t.description == 'test description'
+        assert t.assigned_to.username == 'test-user'
+        assert t.url() == '/p/test/bugs2/1/'
 
         post = Post.query.find(dict(thread_id=ticket.discussion_thread._id,
                                     text={'$ne': 'test comment'})).first()
         assert post is not None, 'No comment about ticket moving'
         message = 'Ticket moved from /p/test/bugs/1/'
-        assert_equal(post.text, message)
+        assert post.text == message
 
         post = Post.query.find(dict(text='test comment')).first()
-        assert_equal(post.thread.discussion_id, app2.config.discussion_id)
-        assert_equal(post.thread.app_config_id, app2.config._id)
-        assert_equal(post.app_config_id, app2.config._id)
+        assert post.thread.discussion_id == app2.config.discussion_id
+        assert post.thread.app_config_id == app2.config._id
+        assert post.app_config_id == app2.config._id
 
     @td.with_tool('test', 'Tickets', 'bugs', username='test-user')
     @td.with_tool('test', 'Tickets', 'bugs2', username='test-user')
@@ -263,16 +263,16 @@ class TestTicketModel(TrackerTestWithModel):
             ticket.custom_fields['_test2'] = 'test val 2'
 
         t = ticket.move(app2.config)
-        assert_equal(t.summary, 'test ticket')
-        assert_equal(t.description, 'test description')
-        assert_equal(t.custom_fields['_test'], 'test val')
+        assert t.summary == 'test ticket'
+        assert t.description == 'test description'
+        assert t.custom_fields['_test'] == 'test val'
         post = Post.query.find(
             dict(thread_id=ticket.discussion_thread._id)).first()
         assert post is not None, 'No comment about ticket moving'
         message = 'Ticket moved from /p/test/bugs/1/'
         message += '\n\nCan\'t be converted:\n'
         message += '\n- **_test2**: test val 2'
-        assert_equal(post.text, message)
+        assert post.text == message
 
     @td.with_tool('test', 'Tickets', 'bugs', username='test-user')
     @td.with_tool('test', 'Tickets', 'bugs2', username='test-user')
@@ -300,9 +300,9 @@ class TestTicketModel(TrackerTestWithModel):
             ticket.assigned_to_id = User.by_username('test-user-0')._id
 
         t = ticket.move(app2.config)
-        assert_equal(t.assigned_to_id, None)
-        assert_equal(t.custom_fields['_user_field'], 'test-user')
-        assert_equal(t.custom_fields['_user_field_2'], '')
+        assert t.assigned_to_id == None
+        assert t.custom_fields['_user_field'] == 'test-user'
+        assert t.custom_fields['_user_field_2'] == ''
         post = Post.query.find(
             dict(thread_id=ticket.discussion_thread._id)).first()
         assert post is not None, 'No comment about ticket moving'
@@ -310,7 +310,7 @@ class TestTicketModel(TrackerTestWithModel):
         message += '\n\nCan\'t be converted:\n'
         message += '\n- **_user_field_2**: test-user-0 (user not in project)'
         message += '\n- **assigned_to**: test-user-0 (user not in project)'
-        assert_equal(post.text, message)
+        assert post.text == message
 
     @td.with_tool('test', 'Tickets', 'bugs', username='test-user')
     def test_attach_with_resettable_stream(self):
@@ -318,7 +318,7 @@ class TestTicketModel(TrackerTestWithModel):
             ticket = Ticket.new()
             ticket.summary = 'test ticket'
             ticket.description = 'test description'
-        assert_equal(len(ticket.attachments), 0)
+        assert len(ticket.attachments) == 0
         f = six.moves.urllib.request.urlopen('file://%s' % __file__)
         TicketAttachment.save_attachment(
             'test_ticket_model.py', ResettableStream(f),
@@ -327,15 +327,15 @@ class TestTicketModel(TrackerTestWithModel):
         # need to refetch since attachments are cached
         session(ticket).expunge(ticket)
         ticket = Ticket.query.get(_id=ticket._id)
-        assert_equal(len(ticket.attachments), 1)
-        assert_equal(ticket.attachments[0].filename, 'test_ticket_model.py')
+        assert len(ticket.attachments) == 1
+        assert ticket.attachments[0].filename == 'test_ticket_model.py'
 
     def test_json_parents(self):
         ticket = Ticket.new()
         json_keys = list(ticket.__json__().keys())
-        assert_in('related_artifacts', json_keys)  # from Artifact
-        assert_in('votes_up', json_keys)  # VotableArtifact
-        assert_in('ticket_num', json_keys)  # Ticket
+        assert 'related_artifacts' in json_keys  # from Artifact
+        assert 'votes_up' in json_keys  # VotableArtifact
+        assert 'ticket_num' in json_keys  # Ticket
         assert ticket.__json__()['assigned_to'] is None
 
     @mock.patch('forgetracker.model.ticket.tsearch')
@@ -349,20 +349,20 @@ class TestTicketModel(TrackerTestWithModel):
         filter = None
         Ticket.paged_query_or_search(app_cfg, user, mongo_query, solr_query, filter, **kw)
         query.assert_called_once_with(app_cfg, user, mongo_query, sort=None, limit=None, page=0, **kw)
-        assert_equal(tsearch.query_filter_choices.call_count, 1)
-        assert_equal(tsearch.query_filter_choices.call_args[0][0], 'solr query')
-        assert_equal(search.call_count, 0)
+        assert tsearch.query_filter_choices.call_count == 1
+        assert tsearch.query_filter_choices.call_args[0][0] == 'solr query'
+        assert search.call_count == 0
         query.reset_mock(), search.reset_mock(), tsearch.reset_mock()
 
         filter = {'status': 'unread'}
         Ticket.paged_query_or_search(app_cfg, user, mongo_query, solr_query, filter, **kw)
         search.assert_called_once_with(app_cfg, user, solr_query, filter=filter, sort=None, limit=None, page=0, **kw)
-        assert_equal(query.call_count, 0)
-        assert_equal(tsearch.query_filter_choices.call_count, 0)
+        assert query.call_count == 0
+        assert tsearch.query_filter_choices.call_count == 0
 
     def test_index(self):
         idx = Ticket(ticket_num=2, summary="ticket2", labels=["mylabel", "other"]).index()
-        assert_equal(idx['summary_t'], 'ticket2')
-        assert_equal(idx['labels_t'], 'mylabel other')
-        assert_equal(idx['reported_by_s'], 'test-user')
-        assert_equal(idx['assigned_to_s'], None)  # must exist at least
+        assert idx['summary_t'] == 'ticket2'
+        assert idx['labels_t'] == 'mylabel other'
+        assert idx['reported_by_s'] == 'test-user'
+        assert idx['assigned_to_s'] == None  # must exist at least
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index e2f2ecaa2..694275746 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -39,7 +39,7 @@ class TestWikiApi(TestRestApiBase):
 
     def test_get_root(self):
         r = self.app.get('/rest/p/test/wiki/')
-        assert_equal(r.json, {'pages': ['Home']})
+        assert r.json == {'pages': ['Home']}
 
     def test_get_page(self):
         r = self.app.get('/p/test/wiki/Home/')
@@ -49,17 +49,17 @@ class TestWikiApi(TestRestApiBase):
                       upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/rest/p/test/wiki/Home/')
         r = json.loads(r.text)
-        assert_equal(r['attachments'][0]['url'],
+        assert (r['attachments'][0]['url'] ==
                      'http://localhost/p/test/wiki/Home/attachment/test_root.py')
-        assert_equal(r['discussion_thread_url'], 'http://localhost/rest%s' %
+        assert (r['discussion_thread_url'] == 'http://localhost/rest%s' %
                      discussion_url)
-        assert_equal(r['discussion_thread']['_id'],
+        assert (r['discussion_thread']['_id'] ==
                      discussion_url.split('/')[-2])
         self.app.post('/wiki/Home/attach',
                       upload_files=[('file_info', '__init__.py', content), ])
         r = self.app.get('/rest/p/test/wiki/Home/')
         r = json.loads(r.text)
-        assert_equal(len(r['attachments']), 2)
+        assert len(r['attachments']) == 2
 
     def test_page_does_not_exist(self):
         r = self.api_get('/rest/p/test/wiki/fake/', status=404)
@@ -70,10 +70,10 @@ class TestWikiApi(TestRestApiBase):
             'labels': 'head hunting,dark side'
         }
         r = self.api_post('/rest/p/test/wiki/Home/', **data)
-        assert_equal(r.status_int, 200)
+        assert r.status_int == 200
         r = self.api_get('/rest/p/test/wiki/Home/')
-        assert_equal(r.json['text'], data['text'])
-        assert_equal(r.json['labels'], data['labels'].split(','))
+        assert r.json['text'] == data['text']
+        assert r.json['labels'] == data['labels'].split(',')
 
     def test_create_page(self):
         data = {
@@ -81,10 +81,10 @@ class TestWikiApi(TestRestApiBase):
             'labels': 'head hunting,dark side'
         }
         r = self.api_post(h.urlquote('/rest/p/test/wiki/tést/'), **data)
-        assert_equal(r.status_int, 200)
+        assert r.status_int == 200
         r = self.api_get(h.urlquote('/rest/p/test/wiki/tést/'))
-        assert_equal(r.json['text'], data['text'])
-        assert_equal(r.json['labels'], data['labels'].split(','))
+        assert r.json['text'] == data['text']
+        assert r.json['labels'] == data['labels'].split(',')
 
     def test_create_page_limit(self):
         data = {
@@ -95,12 +95,12 @@ class TestWikiApi(TestRestApiBase):
         with h.push_config(tg.config, **{'forgewiki.rate_limits': '{}'}):
             r = self.api_post('/rest/p/test/wiki/page1/', status=200, **data)
             p = Page.query.get(title='page1')
-            assert_not_equal(p, None)
+            assert p != None
         # Set rate limit to 1 in first hour of project
         with h.push_config(tg.config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
             r = self.api_post('/rest/p/test/wiki/page2/', status=429, **data)
             p = Page.query.get(title='page2')
-            assert_equal(p, None)
+            assert p == None
 
     # http://blog.watchfire.com/wfblog/2011/10/json-based-xss-exploitation.html
     def test_json_encoding_security(self):
@@ -108,15 +108,15 @@ class TestWikiApi(TestRestApiBase):
                       text='foo <img src=x onerror=alert(1)> bar')
         r = self.api_get('/rest/p/test/wiki/foo.html')
         # raw text is not an HTML tag
-        assert_in(r'foo \u003Cimg src=x onerror=alert(1)> bar', r.text)
+        assert r'foo \u003Cimg src=x onerror=alert(1)> bar' in r.text
         # and json still is parsed into correct content
-        assert_equal(r.json['text'], 'foo <img src=x onerror=alert(1)> bar')
+        assert r.json['text'] == 'foo <img src=x onerror=alert(1)> bar'
 
     def test_json_encoding_directly(self):
         # used in @expose('json'), monkey-patched in our patches.py
-        assert_equal(tg.jsonify.encode('<'), r'"\u003C"')
+        assert tg.jsonify.encode('<') == r'"\u003C"'
         # make sure these are unchanged
-        assert_equal(json.dumps('<'), '"<"')
+        assert json.dumps('<') == '"<"'
 
 
 class TestWikiHasAccess(TestRestApiBase):
@@ -139,13 +139,13 @@ class TestWikiHasAccess(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/wiki/has_access?user=babadook&perm=read',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
         r = self.api_get(
             '/rest/p/test/wiki/has_access?user=test-user&perm=jump',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
 
     def test_has_access_not_admin(self):
         """
@@ -161,10 +161,10 @@ class TestWikiHasAccess(TestRestApiBase):
         r = self.api_get(
             '/rest/p/test/wiki/has_access?user=test-admin&perm=create',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], True)
+        assert r.status_int == 200
+        assert r.json['result'] == True
         r = self.api_get(
             '/rest/p/test/wiki/has_access?user=test-user&perm=create',
             user='root')
-        assert_equal(r.status_int, 200)
-        assert_equal(r.json['result'], False)
+        assert r.status_int == 200
+        assert r.json['result'] == False
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 0c4ea7f0f..05e2b181e 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -80,7 +80,7 @@ class TestRootController(TestController):
 
     def test_root_new_page(self):
         response = self.app.get('/wiki/new_page?title=' + h.urlquote('tést'))
-        assert_equal(response.location, 'http://localhost/wiki/t%C3%A9st/')
+        assert response.location == 'http://localhost/wiki/t%C3%A9st/'
 
     def test_root_new_search(self):
         self.app.get(h.urlquote('/wiki/tést/'))
@@ -95,10 +95,10 @@ class TestRootController(TestController):
     @patch('allura.lib.search.search')
     def test_search(self, search):
         r = self.app.get('/wiki/search/?q=test')
-        assert_in(
-            '<a href="/wiki/search/?q=test&amp;sort=score+asc" class="strong">relevance</a>', r)
-        assert_in(
-            '<a href="/wiki/search/?q=test&amp;sort=mod_date_dt+desc" class="">date</a>', r)
+        assert (
+            '<a href="/wiki/search/?q=test&amp;sort=score+asc" class="strong">relevance</a>' in r)
+        assert (
+            '<a href="/wiki/search/?q=test&amp;sort=mod_date_dt+desc" class="">date</a>' in r)
 
         p = M.Project.query.get(shortname='test')
         r = self.app.get('/wiki/search/?q=test&sort=score+asc')
@@ -147,7 +147,7 @@ class TestRootController(TestController):
         assert btn is not None, "Can't find a help button"
         div = r.html.find('div', attrs={'id': 'lightbox_search_help_modal'})
         assert div is not None, "Can't find help text"
-        assert_in('To search for an exact phrase', div.text)
+        assert 'To search for an exact phrase' in div.text
 
     def test_nonexistent_page_edit(self):
         resp = self.app.get(h.urlquote('/wiki/tést/'))
@@ -188,7 +188,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': 'test label',
                 }).follow()
-        assert_in('<a href="/p/test/wiki/search/?q=labels_t:%22test label%22&parser=standard">test label (1)</a>',
+        assert ('<a href="/p/test/wiki/search/?q=labels_t:%22test label%22&parser=standard">test label (1)</a>' in
                   response)
 
     def test_title_slashes(self):
@@ -347,14 +347,14 @@ class TestRootController(TestController):
                                             <script>alert(1)</script>""")
         self.app.post('/wiki/testdiff/update', params=d)
         response = self.app.get('/wiki/testdiff/diff?v1=1&v2=2')
-        assert_in('# Now fix <del> permissons. </del> <ins> permissions. </ins> '
-                  'Wrong permissions may cause <ins> a </ins> massive slowdown!',
+        assert ('# Now fix <del> permissons. </del> <ins> permissions. </ins> '
+                  'Wrong permissions may cause <ins> a </ins> massive slowdown!' in
                   response)
-        assert_not_in('<script>alert', response)
-        assert_in('&lt;script&gt;alert', response)
+        assert '<script>alert' not in response
+        assert '&lt;script&gt;alert' in response
         response = self.app.get('/wiki/testdiff/diff?v1=2&v2=1')
-        assert_in('# Now fix <del> permissions. </del> <ins> permissons. </ins> '
-                  'Wrong permissions may cause <del> a </del> massive slowdown!',
+        assert ('# Now fix <del> permissions. </del> <ins> permissons. </ins> '
+                  'Wrong permissions may cause <del> a </del> massive slowdown!' in
                   response)
 
     def test_page_raw(self):
@@ -405,8 +405,8 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': '',
                 })
-        assert_equal(spam_checker.check.call_args[0][0], 'tést\nsometext')
-        assert_equal(response.location, 'http://localhost/wiki/t%C3%A9st/')
+        assert spam_checker.check.call_args[0][0] == 'tést\nsometext'
+        assert response.location == 'http://localhost/wiki/t%C3%A9st/'
 
     def test_page_get_markdown(self):
         self.app.post(
@@ -450,7 +450,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': 'yellow,green',
                 })
-        assert_equal(response.location, 'http://localhost/wiki/t%C3%A9st/')
+        assert response.location == 'http://localhost/wiki/t%C3%A9st/'
         response = self.app.post(
             h.urlquote('/wiki/tést/update'),
             params={
@@ -458,7 +458,7 @@ class TestRootController(TestController):
                 'text': 'sometext',
                 'labels': 'yellow',
                 })
-        assert_equal(response.location, 'http://localhost/wiki/t%C3%A9st/')
+        assert response.location == 'http://localhost/wiki/t%C3%A9st/'
 
     def test_page_label_count(self):
         labels = "label"
@@ -539,7 +539,7 @@ class TestRootController(TestController):
         self.app.post(h.urlquote('/wiki/tést/attach'), upload_files=[upload])
         page_editor = self.app.get(h.urlquote('/wiki/tést/edit'))
         download = page_editor.click(description=file_name)
-        assert_true(download.body == file_data)
+        assert download.body == file_data
 
     def test_new_image_attachment_content(self):
         self.app.post('/wiki/TEST/update', params={
@@ -679,7 +679,7 @@ class TestRootController(TestController):
             'labels': '',
             })
         homepage_admin = self.app.get('/admin/wiki/home', validate_chunk=True)
-        assert_equal(homepage_admin.form['new_home'].value, 'Home')
+        assert homepage_admin.form['new_home'].value == 'Home'
         homepage_admin.form['new_home'].value = 'our_néw_home'
         homepage_admin.form.submit()
         root_path = self.app.get('/wiki/', status=301)
@@ -783,7 +783,7 @@ class TestRootController(TestController):
         # first request caches html, second serves from cache
         r = self.app.get('/wiki/cache/')
         r = self.app.get('/wiki/cache/')
-        assert_true(html in r)
+        assert html in r
 
     def test_page_delete(self):
         self.app.post('/wiki/aaa/update', params={
@@ -814,7 +814,7 @@ class TestRootController(TestController):
         # undelete it
         undelete_url = deletedpath + 'undelete'
         response = self.app.post(undelete_url)
-        assert_equal(response.json, {'location': './edit'})
+        assert response.json == {'location': './edit'}
         response = self.app.get(deletedpath + 'edit')
         assert 'Edit bbb' in response
 
@@ -877,20 +877,20 @@ class TestRootController(TestController):
         # Set rate limit to unlimit
         with h.push_config(config, **{'forgewiki.rate_limits': '{}'}):
             r = self.app.get('/p/test/wiki/new-page-title/')
-            assert_equal(r.status_int, 302)
-            assert_equal(
-                r.location,
+            assert r.status_int == 302
+            assert (
+                r.location ==
                 'http://localhost/p/test/wiki/new-page-title/edit')
-            assert_equal(self.webflash(r), '')
+            assert self.webflash(r) == ''
         # Set rate limit to 1 in first hour of project
         with h.push_config(config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
             r = self.app.get('/p/test/wiki/new-page-title/')
-            assert_equal(r.status_int, 302)
-            assert_equal(r.location, 'http://localhost/p/test/wiki/')
+            assert r.status_int == 302
+            assert r.location == 'http://localhost/p/test/wiki/'
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(
-                wf['message'],
+            assert wf['status'] == 'error'
+            assert (
+                wf['message'] ==
                 'Page create/edit rate limit exceeded. Please try again later.')
 
     def test_rate_limit_update(self):
@@ -899,23 +899,23 @@ class TestRootController(TestController):
             r = self.app.post(
                 '/p/test/wiki/page1/update',
                 dict(text='Some text', title='page1')).follow()
-            assert_in('Some text', r)
+            assert 'Some text' in r
             p = model.Page.query.get(title='page1')
-            assert_not_equal(p, None)
+            assert p != None
         # Set rate limit to 1 in first hour of project
         with h.push_config(config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
             r = self.app.post(
                 '/p/test/wiki/page2/update',
                 dict(text='Some text', title='page2'))
-            assert_equal(r.status_int, 302)
-            assert_equal(r.location, 'http://localhost/p/test/wiki/')
+            assert r.status_int == 302
+            assert r.location == 'http://localhost/p/test/wiki/'
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(
-                wf['message'],
+            assert wf['status'] == 'error'
+            assert (
+                wf['message'] ==
                 'Page create/edit rate limit exceeded. Please try again later.')
             p = model.Page.query.get(title='page2')
-            assert_equal(p, None)
+            assert p == None
 
     def test_rate_limit_by_user(self):
         # also test that multiple edits to a page counts as one page towards the limit
@@ -926,45 +926,45 @@ class TestRootController(TestController):
         with h.push_config(config, **{'forgewiki.rate_limits_per_user': '{"3600": 5}'}):
             r = self.app.post('/p/test/wiki/page123/update',  # page 4 (remember, 3 other projects' wiki pages)
                               dict(text='Starting a new page, ok', title='page123'))
-            assert_equal(self.webflash(r), '')
+            assert self.webflash(r) == ''
             r = self.app.post('/p/test/wiki/page123/update',
                               dict(text='Editing some', title='page123'))
-            assert_equal(self.webflash(r), '')
+            assert self.webflash(r) == ''
             r = self.app.post('/p/test/wiki/page123/update',
                               dict(text='Still editing', title='page123'))
-            assert_equal(self.webflash(r), '')
+            assert self.webflash(r) == ''
             r = self.app.post('/p/test/wiki/pageABC/update',  # page 5
                               dict(text='Another new page', title='pageABC'))
-            assert_equal(self.webflash(r), '')
+            assert self.webflash(r) == ''
             r = self.app.post('/p/test/wiki/pageZZZZZ/update',  # page 6
                               dict(text='This new page hits the limit', title='pageZZZZZ'))
             wf = json.loads(self.webflash(r))
-            assert_equal(wf['status'], 'error')
-            assert_equal(wf['message'], 'Page create/edit rate limit exceeded. Please try again later.')
+            assert wf['status'] == 'error'
+            assert wf['message'] == 'Page create/edit rate limit exceeded. Please try again later.'
 
     def test_sidebar_admin_menu(self):
         r = self.app.get('/p/test/wiki/Home/')
         menu = r.html.find('div', {'id': 'sidebar-admin-menu'})
-        assert_equal(menu['class'], ['hidden'])  # (not expanded)
+        assert menu['class'] == ['hidden']  # (not expanded)
         menu = [li.find('span').getText() for li in menu.findAll('li')]
-        assert_equal(
-            menu,
+        assert (
+            menu ==
             ['Set Home', 'Permissions', 'Options', 'Rename', 'Delete Everything'])
 
     def test_sidebar_admin_menu_is_expanded(self):
         r = self.app.get('/p/test/admin/wiki/permissions')
         menu = r.html.find('div', {'id': 'sidebar-admin-menu'})
-        assert_not_in('hidden', menu.get('class', []))  # expanded
+        assert 'hidden' not in menu.get('class', [])  # expanded
 
     def test_sidebar_admin_menu_invisible_to_not_admin(self):
         def assert_invisible_for(username):
             env = {'username': str(username)}
             r = self.app.get('/p/test/wiki/Home/', extra_environ=env)
             menu = r.html.find('div', {'id': 'sidebar-admin-menu'})
-            assert_equal(menu, None)
+            assert menu == None
         assert_invisible_for('*anonymous')
         assert_invisible_for('test-user')
 
     def test_no_index_tag_on_empty_wiki(self):
         r = self.app.get('/u/test-user/wiki/Home/')
-        assert_in('content="noindex, follow"', r.text)
+        assert 'content="noindex, follow"' in r.text
diff --git a/ForgeWiki/forgewiki/tests/test_app.py b/ForgeWiki/forgewiki/tests/test_app.py
index 86ad91743..3dc723c68 100644
--- a/ForgeWiki/forgewiki/tests/test_app.py
+++ b/ForgeWiki/forgewiki/tests/test_app.py
@@ -71,22 +71,22 @@ class TestBulkExport:
         f.seek(0)
         wiki = json.loads(f.read())
         pages = sorted(wiki['pages'], key=operator.itemgetter('title'))
-        assert_equal(len(pages), 3)
-        assert_equal(pages[0]['title'], 'A New Hope')
-        assert_equal(pages[0]['text'], 'Star Wars Episode IV: A New Hope')
-        assert_equal(pages[0]['mod_date'], '2013-07-05 00:00:00')
-        assert_equal(pages[0]['labels'], ['star wars', 'movies'])
-        assert_equal(len(pages[0]['discussion_thread']['posts']), 2)
-
-        assert_equal(pages[1]['title'], 'Return of the Jedi')
-        assert_equal(pages[1]['text'],
+        assert len(pages) == 3
+        assert pages[0]['title'] == 'A New Hope'
+        assert pages[0]['text'] == 'Star Wars Episode IV: A New Hope'
+        assert pages[0]['mod_date'] == '2013-07-05 00:00:00'
+        assert pages[0]['labels'] == ['star wars', 'movies']
+        assert len(pages[0]['discussion_thread']['posts']) == 2
+
+        assert pages[1]['title'] == 'Return of the Jedi'
+        assert (pages[1]['text'] ==
                      'Star Wars Episode VI: Return of the Jedi')
-        assert_equal(len(pages[1]['discussion_thread']['posts']), 0)
+        assert len(pages[1]['discussion_thread']['posts']) == 0
 
-        assert_equal(pages[2]['title'], 'The Empire Strikes Back')
-        assert_equal(pages[2]['text'],
+        assert pages[2]['title'] == 'The Empire Strikes Back'
+        assert (pages[2]['text'] ==
                      'Star Wars Episode V: The Empire Strikes Back')
-        assert_equal(len(pages[2]['discussion_thread']['posts']), 0)
+        assert len(pages[2]['discussion_thread']['posts']) == 0
 
     def add_page_with_attachmetns(self):
         self.page = WM.Page.upsert('ZTest_title')
@@ -159,7 +159,7 @@ class TestApp:
         msg = dict(payload=message, message_id=message_id, headers={'Subject': 'test'})
         self.wiki.handle_message('A_New_Hope', msg)
         post = M.Post.query.get(_id=message_id)
-        assert_equal(post["text"], message)
+        assert post["text"] == message
 
     def test_uninstall(self):
         assert WM.Page.query.get(title='A New Hope')
diff --git a/ForgeWiki/forgewiki/tests/test_wiki_roles.py b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
index 605c4cedc..e03880976 100644
--- a/ForgeWiki/forgewiki/tests/test_wiki_roles.py
+++ b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
@@ -44,12 +44,12 @@ def test_role_assignments():
     def check_access(perm):
         pred = security.has_access(c.app, perm)
         return pred(user=admin), pred(user=user), pred(user=anon)
-    assert_equal(check_access('configure'), (True, False, False))
-    assert_equal(check_access('read'), (True, True, True))
-    assert_equal(check_access('create'), (True, False, False))
-    assert_equal(check_access('edit'), (True, False, False))
-    assert_equal(check_access('delete'), (True, False, False))
-    assert_equal(check_access('unmoderated_post'), (True, True, False))
-    assert_equal(check_access('post'), (True, True, False))
-    assert_equal(check_access('moderate'), (True, False, False))
-    assert_equal(check_access('admin'), (True, False, False))
+    assert check_access('configure') == (True, False, False)
+    assert check_access('read') == (True, True, True)
+    assert check_access('create') == (True, False, False)
+    assert check_access('edit') == (True, False, False)
+    assert check_access('delete') == (True, False, False)
+    assert check_access('unmoderated_post') == (True, True, False)
+    assert check_access('post') == (True, True, False)
+    assert check_access('moderate') == (True, False, False)
+    assert check_access('admin') == (True, False, False)


[allura] 03/03: fixup! [#8455] converted the remaining modules fully to pytest

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dill0wn pushed a commit to branch dw/8455-part2
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 85f479ba3410dbefc2dd6bfb2dd49a2a2b18a0de
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Wed Sep 21 16:04:17 2022 +0000

    fixup! [#8455] converted the remaining modules fully to pytest
---
 Allura/allura/tests/test_patches.py  | 8 ++++----
 Allura/allura/tests/test_webhooks.py | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Allura/allura/tests/test_patches.py b/Allura/allura/tests/test_patches.py
index ddaa0027a..b66957c6f 100644
--- a/Allura/allura/tests/test_patches.py
+++ b/Allura/allura/tests/test_patches.py
@@ -32,7 +32,7 @@ def test_with_trailing_slash():
     patches.apply()
     with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.with_trailing_slash(empty_func)()
-    assert raised.exception.location == 'http://localhost/foo/bar/'
+    assert raised.value.location == 'http://localhost/foo/bar/'
 
 
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar/?a=b'))
@@ -47,7 +47,7 @@ def test_with_trailing_slash_qs():
     patches.apply()
     with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.with_trailing_slash(empty_func)()
-    assert raised.exception.location == 'http://localhost/foo/bar/?foo=bar&baz=bam'
+    assert raised.value.location == 'http://localhost/foo/bar/?foo=bar&baz=bam'
 
 
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar/'))
@@ -55,7 +55,7 @@ def test_without_trailing_slash():
     patches.apply()
     with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.without_trailing_slash(empty_func)()
-    assert raised.exception.location == 'http://localhost/foo/bar'
+    assert raised.value.location == 'http://localhost/foo/bar'
 
 
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar?a=b'))
@@ -70,4 +70,4 @@ def test_without_trailing_slash_qs():
     patches.apply()
     with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.without_trailing_slash(empty_func)()
-    assert raised.exception.location == 'http://localhost/foo/bar?foo=bar&baz=bam'
+    assert raised.value.location == 'http://localhost/foo/bar?foo=bar&baz=bam'
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index c1eeaa0e8..b2958d7d2 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -97,10 +97,10 @@ class TestValidators(TestWebhookBase):
         v = WebhookValidator(sender=sender, app=app, not_empty=True)
         with pytest.raises(Invalid) as cm:
             v.to_python(None)
-        assert cm.exception.msg == 'Please enter a value'
+        assert cm.value.msg == 'Please enter a value'
         with pytest.raises(Invalid) as cm:
             v.to_python('invalid id')
-        assert cm.exception.msg == 'Invalid webhook'
+        assert cm.value.msg == 'Invalid webhook'
 
         wh = M.Webhook(type='invalid type',
                        app_config_id=invalid_app.config._id,
@@ -110,14 +110,14 @@ class TestValidators(TestWebhookBase):
         # invalid type
         with pytest.raises(Invalid) as cm:
             v.to_python(wh._id)
-        assert cm.exception.msg == 'Invalid webhook'
+        assert cm.value.msg == 'Invalid webhook'
 
         wh.type = 'repo-push'
         session(wh).flush(wh)
         # invalild app
         with pytest.raises(Invalid) as cm:
             v.to_python(wh._id)
-        assert cm.exception.msg == 'Invalid webhook'
+        assert cm.value.msg == 'Invalid webhook'
 
         wh.app_config_id = app.config._id
         session(wh).flush(wh)


[allura] 02/03: [#8455] converted the remaining modules fully to pytest

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dill0wn pushed a commit to branch dw/8455-part2
in repository https://gitbox.apache.org/repos/asf/allura.git

commit dfb1887fc1ea0288f7b799a8f21c78705e85e244
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Fri Sep 16 18:46:46 2022 +0000

    [#8455] converted the remaining modules fully to pytest
---
 Allura/allura/tests/functional/test_discuss.py     |  2 +-
 Allura/allura/tests/model/test_artifact.py         |  5 ++--
 Allura/allura/tests/test_app.py                    |  6 ++--
 Allura/allura/tests/test_commands.py               | 33 +++++++++++-----------
 Allura/allura/tests/test_helpers.py                | 11 ++++----
 Allura/allura/tests/test_mail_util.py              | 26 ++++++++---------
 Allura/allura/tests/test_multifactor.py            | 24 ++++++++--------
 Allura/allura/tests/test_patches.py                | 13 ++++-----
 Allura/allura/tests/test_plugin.py                 | 22 +++++----------
 Allura/allura/tests/test_security.py               |  4 +--
 Allura/allura/tests/test_utils.py                  | 13 +++------
 Allura/allura/tests/test_webhooks.py               | 15 ++++------
 Allura/allura/tests/unit/spam/test_akismet.py      |  2 +-
 .../tests/unit/test_helpers/test_set_context.py    |  8 +++---
 .../allura/tests/unit/test_package_path_loader.py  |  8 +++---
 .../forgeactivity/tests/functional/test_rest.py    |  8 +++---
 .../forgeactivity/tests/functional/test_root.py    |  8 +++---
 ForgeBlog/forgeblog/tests/functional/test_rest.py  |  4 +--
 ForgeBlog/forgeblog/tests/test_app.py              |  4 +--
 ForgeBlog/forgeblog/tests/test_commands.py         |  2 +-
 ForgeBlog/forgeblog/tests/test_roles.py            |  2 +-
 ForgeBlog/forgeblog/tests/unit/__init__.py         |  4 +--
 .../forgediscussion/tests/functional/test_forum.py | 16 +++++------
 .../tests/functional/test_forum_admin.py           |  4 +--
 .../tests/functional/test_import.py                |  4 +--
 .../forgediscussion/tests/functional/test_rest.py  |  6 ++--
 ForgeDiscussion/forgediscussion/tests/test_app.py  |  2 +-
 .../forgediscussion/tests/test_forum_roles.py      |  2 +-
 .../forgefeedback/tests/functional/test_root.py    |  6 ----
 .../forgefeedback/tests/test_feedback_roles.py     |  2 +-
 ForgeFeedback/forgefeedback/tests/unit/__init__.py |  4 +--
 .../tests/unit/test_root_controller.py             |  4 +--
 .../forgefiles/tests/functional/test_root.py       |  3 --
 ForgeFiles/forgefiles/tests/model/__init__.py      |  4 +--
 ForgeFiles/forgefiles/tests/test_files_roles.py    |  2 +-
 .../forgegit/tests/functional/test_controllers.py  | 32 ++++++++++-----------
 ForgeGit/forgegit/tests/model/test_repository.py   | 12 ++++----
 ForgeGit/forgegit/tests/test_git_app.py            |  2 +-
 ForgeGit/forgegit/tests/test_tasks.py              |  6 ++--
 .../forgeimporters/github/tests/test_code.py       |  2 +-
 .../forgeimporters/github/tests/test_oauth.py      |  4 +--
 .../forgeimporters/github/tests/test_utils.py      |  2 +-
 .../forgeimporters/github/tests/test_wiki.py       |  2 +-
 .../forgeimporters/tests/forge/test_discussion.py  | 11 +++-----
 .../forgeimporters/tests/forge/test_tracker.py     | 10 +++----
 .../tests/github/functional/test_github.py         |  4 +--
 .../forgeimporters/tests/github/test_extractor.py  |  2 +-
 .../forgeimporters/tests/github/test_tracker.py    |  6 ++--
 ForgeImporters/forgeimporters/tests/test_base.py   | 10 +++----
 .../forgeimporters/trac/tests/test_tickets.py      |  6 ++--
 ForgeLink/forgelink/tests/functional/test_rest.py  |  8 +++---
 ForgeLink/forgelink/tests/test_app.py              |  2 +-
 .../forgesvn/tests/functional/test_controllers.py  |  8 +++---
 ForgeSVN/forgesvn/tests/model/test_repository.py   | 24 ++++++++--------
 .../forgesvn/tests/model/test_svnimplementation.py |  2 +-
 ForgeSVN/forgesvn/tests/test_svn_app.py            |  2 +-
 ForgeSVN/forgesvn/tests/test_tasks.py              |  4 +--
 .../forgeshorturl/tests/functional/test.py         |  4 +--
 .../tests/command/test_fix_discussion.py           |  2 +-
 .../forgetracker/tests/functional/test_rest.py     | 16 +++++------
 .../forgetracker/tests/functional/test_root.py     | 24 ++++++----------
 ForgeTracker/forgetracker/tests/test_app.py        |  2 +-
 .../forgetracker/tests/test_tracker_roles.py       |  2 +-
 ForgeTracker/forgetracker/tests/unit/__init__.py   |  4 +--
 .../forgetracker/tests/unit/test_globals_model.py  |  4 +--
 .../tests/unit/test_root_controller.py             | 12 ++++----
 .../forgetracker/tests/unit/test_ticket_model.py   | 12 ++------
 ForgeUserStats/forgeuserstats/tests/test_model.py  |  2 +-
 ForgeUserStats/forgeuserstats/tests/test_stats.py  |  8 +++---
 ForgeWiki/forgewiki/tests/functional/test_rest.py  |  8 +++---
 ForgeWiki/forgewiki/tests/functional/test_root.py  |  4 +--
 ForgeWiki/forgewiki/tests/test_app.py              |  4 +--
 ForgeWiki/forgewiki/tests/test_wiki_roles.py       |  2 +-
 scripts/perf/call_count.py                         |  4 +--
 74 files changed, 254 insertions(+), 304 deletions(-)

diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 8adb1a1af..3c0ed26ef 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -17,7 +17,7 @@
 
 import os
 from mock import patch
-from alluratest.tools import assert_in, assert_not_in, assert_equal, assert_false, assert_true, assert_raises
+import pytest
 from webtest.app import AppError
 from ming.odm import session
 
diff --git a/Allura/allura/tests/model/test_artifact.py b/Allura/allura/tests/model/test_artifact.py
index 8f0100e82..25863cc6f 100644
--- a/Allura/allura/tests/model/test_artifact.py
+++ b/Allura/allura/tests/model/test_artifact.py
@@ -22,8 +22,9 @@ import re
 from datetime import datetime
 
 from tg import tmpl_context as c
-from alluratest.tools import with_setup, assert_raises, assert_equal
+from alluratest.tools import with_setup
 from mock import patch
+import pytest
 from ming.orm.ormsession import ThreadLocalORMSession
 from ming.orm import Mapper
 from bson import ObjectId
@@ -182,7 +183,7 @@ def test_versioning():
     assert ss.shorthand_id() == pg.shorthand_id() + '#2'
     assert ss.title == pg.title
     assert ss.text == pg.text
-    assert_raises(IndexError, pg.get_version, 42)
+    pytest.raises(IndexError, pg.get_version, 42)
     pg.revert(1)
     pg.commit()
     ThreadLocalORMSession.flush_all()
diff --git a/Allura/allura/tests/test_app.py b/Allura/allura/tests/test_app.py
index 024c12fd3..71733a2d5 100644
--- a/Allura/allura/tests/test_app.py
+++ b/Allura/allura/tests/test_app.py
@@ -18,7 +18,7 @@
 from tg import tmpl_context as c
 import mock
 from ming.base import Object
-from alluratest.tools import assert_raises
+import pytest
 from formencode import validators as fev
 
 from alluratest.controller import setup_unit_test
@@ -73,8 +73,8 @@ def test_config_option_with_validator():
     v = fev.NotEmpty()
     opt = app.ConfigOption('test1', str, None, validator=v)
     assert opt.validate('val') == 'val'
-    assert_raises(fev.Invalid, opt.validate, None)
-    assert_raises(fev.Invalid, opt.validate, '')
+    pytest.raises(fev.Invalid, opt.validate, None)
+    pytest.raises(fev.Invalid, opt.validate, '')
 
 
 @with_setup(setup_method)
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index f7440e3a1..fa187c1fd 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -19,7 +19,7 @@
 import datetime
 
 import six
-from alluratest.tools import assert_raises, assert_in, with_setup
+from alluratest.tools import with_setup
 from testfixtures import OutputCapture
 
 from datadiff.tools import assert_equal
@@ -27,6 +27,7 @@ from datadiff.tools import assert_equal
 from ming.base import Object
 from ming.orm import ThreadLocalORMSession
 from mock import Mock, call, patch
+import pytest
 import pymongo
 import pkg_resources
 
@@ -58,7 +59,7 @@ def test_script():
     cmd = script.ScriptCommand('script')
     cmd.run(
         [test_config, pkg_resources.resource_filename('allura', 'tests/tscript.py')])
-    assert_raises(ValueError, cmd.run,
+    pytest.raises(ValueError, cmd.run,
                   [test_config, pkg_resources.resource_filename('allura', 'tests/tscript_error.py')])
 
 
@@ -80,9 +81,9 @@ def test_set_neighborhood_max_projects():
     assert neighborhood.features['max_projects'] is None
 
     # check validation
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'max_projects', 'string'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'max_projects', '2.8'])
 
 
@@ -104,11 +105,11 @@ def test_set_neighborhood_private():
     assert not neighborhood.features['private_projects']
 
     # check validation
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'private_projects', 'string'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'private_projects', '1'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'private_projects', '2.8'])
 
 
@@ -130,11 +131,11 @@ def test_set_neighborhood_google_analytics():
     assert not neighborhood.features['google_analytics']
 
     # check validation
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'google_analytics', 'string'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'google_analytics', '1'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'google_analytics', '2.8'])
 
 
@@ -161,15 +162,15 @@ def test_set_neighborhood_css():
     assert neighborhood.features['css'] == 'custom'
 
     # check validation
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'css', 'string'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'css', '1'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'css', '2.8'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'css', 'None'])
-    assert_raises(InvalidNBFeatureValueError, cmd.run,
+    pytest.raises(InvalidNBFeatureValueError, cmd.run,
                   [test_config, str(n_id), 'css', 'True'])
 
 
@@ -363,7 +364,7 @@ class TestTaskdCleanupCommand:
         self.cmd_class._complete_suspicious_tasks = lambda x: []
 
     def teardown_method(self, method):
-        # need to clean up setUp mocking for unit tests below to work properly
+        # need to clean up setup_method mocking for unit tests below to work properly
         self.cmd_class._check_taskd_status = self.old_check_taskd_status
         self.cmd_class._check_task = self.old_check_task
         self.cmd_class._busy_tasks = self.old_busy_tasks
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index 6e03cb8c5..93a2347a1 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -23,12 +23,13 @@ import time
 import PIL
 from mock import Mock, patch
 from tg import tmpl_context as c
-from alluratest.tools import assert_equals, assert_raises, module_not_available, with_setup
+from alluratest.tools import module_not_available, with_setup
 from datadiff import tools as dd
 from webob import Request
 from webob.exc import HTTPUnauthorized
 from ming.orm import ThreadLocalORMSession
 from markupsafe import Markup
+import pytest
 
 from allura import model as M
 from allura.lib import exceptions as exc
@@ -665,24 +666,24 @@ class TestRateLimit(TestCase):
 
             start_date = now - timedelta(seconds=30)
             h.rate_limit(self.key_comment, 0, start_date)
-            with assert_raises(exc.RatelimitError):
+            with pytest.raises(exc.RatelimitError):
                 h.rate_limit(self.key_comment, 1, start_date)
 
             start_date = now - timedelta(seconds=61)
             h.rate_limit(self.key_comment, 1, start_date)
             h.rate_limit(self.key_comment, 2, start_date)
-            with assert_raises(exc.RatelimitError):
+            with pytest.raises(exc.RatelimitError):
                 h.rate_limit(self.key_comment, 3, start_date)
 
             start_date = now - timedelta(seconds=86301)
             h.rate_limit(self.key_comment, 19, start_date)
-            with assert_raises(exc.RatelimitError):
+            with pytest.raises(exc.RatelimitError):
                 h.rate_limit(self.key_comment, 20, start_date)
 
             start_date = now - timedelta(seconds=86401)
             h.rate_limit(self.key_comment, 21, start_date)
             h.rate_limit(self.key_comment, 49, start_date)
-            with assert_raises(exc.RatelimitError):
+            with pytest.raises(exc.RatelimitError):
                 h.rate_limit(self.key_comment, 50, start_date)
 
 
diff --git a/Allura/allura/tests/test_mail_util.py b/Allura/allura/tests/test_mail_util.py
index 33e80bfb0..acc4c22dd 100644
--- a/Allura/allura/tests/test_mail_util.py
+++ b/Allura/allura/tests/test_mail_util.py
@@ -20,7 +20,7 @@ from six.moves.email_mime_multipart import MIMEMultipart
 from six.moves.email_mime_text import MIMEText
 
 import mock
-from alluratest.tools import raises, assert_equal, assert_false, assert_true, assert_in
+import pytest
 from ming.orm import ThreadLocalORMSession
 from tg import config as tg_config
 
@@ -39,7 +39,7 @@ from allura.lib.mail_util import (
 from allura.lib.exceptions import AddressException
 from alluratest.pytest_helpers import with_nose_compatibility
 from allura.tests import decorators as td
-import six
+
 
 config = ConfigProxy(
     common_suffix='forgemail.domain',
@@ -55,9 +55,9 @@ class TestReactor(unittest.TestCase):
         ThreadLocalORMSession.flush_all()
         ThreadLocalORMSession.close_all()
 
-    @raises(AddressException)
     def test_parse_address_bad_domain(self):
-        parse_address('foo@bar.com')
+        with pytest.raises(AddressException):
+            parse_address('foo@bar.com')
 
     @td.with_wiki
     @mock.patch.dict(tg_config, {'forgemail.domain.alternates': '.secondary.com .tertiary.com'})
@@ -65,17 +65,17 @@ class TestReactor(unittest.TestCase):
         parse_address('foo@wiki.test.p.secondary.com')
         parse_address('foo@wiki.test.p.tertiary.com')
 
-    @raises(AddressException)
     def test_parse_address_bad_project(self):
-        parse_address('foo@wiki.unicorns.p' + config.common_suffix)
+        with pytest.raises(AddressException):
+            parse_address('foo@wiki.unicorns.p' + config.common_suffix)
 
-    @raises(AddressException)
     def test_parse_address_missing_tool(self):
-        parse_address('foo@test.p' + config.common_suffix)
+        with pytest.raises(AddressException):
+            parse_address('foo@test.p' + config.common_suffix)
 
-    @raises(AddressException)
     def test_parse_address_bad_tool(self):
-        parse_address('foo@hammer.test.p' + config.common_suffix)
+        with pytest.raises(AddressException):
+            parse_address('foo@hammer.test.p' + config.common_suffix)
 
     @td.with_wiki
     def test_parse_address_good(self):
@@ -214,10 +214,10 @@ Content-Type: text/html; charset="utf-8"
 @with_nose_compatibility
 class TestHeader:
 
-    @raises(TypeError)
     def test_bytestring(self):
-        our_header = Header(b'[asdf2:wiki] Discussion for Home page')
-        assert our_header.encode() == '[asdf2:wiki] Discussion for Home page'
+        with pytest.raises(TypeError):
+            our_header = Header(b'[asdf2:wiki] Discussion for Home page')
+            assert our_header.encode() == '[asdf2:wiki] Discussion for Home page'
 
     def test_ascii(self):
         our_header = Header('[asdf2:wiki] Discussion for Home page')
diff --git a/Allura/allura/tests/test_multifactor.py b/Allura/allura/tests/test_multifactor.py
index ba7780f3b..3ce6fdb31 100644
--- a/Allura/allura/tests/test_multifactor.py
+++ b/Allura/allura/tests/test_multifactor.py
@@ -23,7 +23,7 @@ from paste.deploy.converters import asint
 import ming
 from cryptography.hazmat.primitives.twofactor import InvalidToken
 from mock import patch, Mock
-from alluratest.tools import assert_equal, assert_raises
+import pytest
 from tg import config
 
 from allura import model as M
@@ -112,11 +112,11 @@ class TestTotpService:
         srv.verify(totp, '283397', None)
 
         time.return_value = self.sample_time + 60
-        with assert_raises(InvalidToken):
+        with pytest.raises(InvalidToken):
             srv.verify(totp, '283397', None)
 
         time.return_value = self.sample_time - 30
-        with assert_raises(InvalidToken):
+        with pytest.raises(InvalidToken):
             srv.verify(totp, '283397', None)
 
     def test_get_qr_code(self):
@@ -166,12 +166,12 @@ class TestAnyTotpServiceImplementation:
         totp = srv.Totp(key=self.sample_key)
 
         # 4th attempt (good or bad) will trip over the default limit of 3 in 30s
-        with assert_raises(InvalidToken):
+        with pytest.raises(InvalidToken):
             srv.verify(totp, '34dfvdasf', user)
-        with assert_raises(InvalidToken):
+        with pytest.raises(InvalidToken):
             srv.verify(totp, '234asdfsadf', user)
         srv.verify(totp, '283397', user)
-        with assert_raises(MultifactorRateLimitError):
+        with pytest.raises(MultifactorRateLimitError):
             srv.verify(totp, '283397', user)
 
 
@@ -269,9 +269,9 @@ class TestAnyRecoveryCodeServiceImplementation:
     def test_verify_fail(self):
         recovery = self.Service()
         user = self.mock_user()
-        with assert_raises(InvalidRecoveryCode):
+        with pytest.raises(InvalidRecoveryCode):
             recovery.verify_and_remove_code(user, '11111')
-        with assert_raises(InvalidRecoveryCode):
+        with pytest.raises(InvalidRecoveryCode):
             recovery.verify_and_remove_code(user, '')
 
     def test_verify_and_remove_code(self):
@@ -296,12 +296,12 @@ class TestAnyRecoveryCodeServiceImplementation:
         recovery.replace_codes(user, codes)
 
         # 4th attempt (good or bad) will trip over the default limit of 3 in 30s
-        with assert_raises(InvalidRecoveryCode):
+        with pytest.raises(InvalidRecoveryCode):
             recovery.verify_and_remove_code(user, '13485u0233')
-        with assert_raises(InvalidRecoveryCode):
+        with pytest.raises(InvalidRecoveryCode):
             recovery.verify_and_remove_code(user, '34123rdxafs')
         recovery.verify_and_remove_code(user, '11111')
-        with assert_raises(MultifactorRateLimitError):
+        with pytest.raises(MultifactorRateLimitError):
             recovery.verify_and_remove_code(user, '22222')
 
 
@@ -345,5 +345,5 @@ class TestGoogleAuthenticatorPamFilesystemRecoveryCodeService(TestAnyRecoveryCod
         GoogleAuthenticatorPamFilesystemTotpService().set_secret_key(self.mock_user(), None)
 
         # then it errors because no .google-authenticator file
-        with assert_raises(IOError):
+        with pytest.raises(IOError):
             super().test_replace_codes()
diff --git a/Allura/allura/tests/test_patches.py b/Allura/allura/tests/test_patches.py
index 0beb9ce96..ddaa0027a 100644
--- a/Allura/allura/tests/test_patches.py
+++ b/Allura/allura/tests/test_patches.py
@@ -17,10 +17,7 @@
 
 import webob
 from mock import patch
-from alluratest.tools import (
-    assert_equal,
-    assert_raises,
-)
+import pytest
 import tg
 
 from allura.lib import patches
@@ -33,7 +30,7 @@ def empty_func():
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar'))
 def test_with_trailing_slash():
     patches.apply()
-    with assert_raises(webob.exc.HTTPMovedPermanently) as raised:
+    with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.with_trailing_slash(empty_func)()
     assert raised.exception.location == 'http://localhost/foo/bar/'
 
@@ -48,7 +45,7 @@ def test_with_trailing_slash_ok():
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar?foo=bar&baz=bam'))
 def test_with_trailing_slash_qs():
     patches.apply()
-    with assert_raises(webob.exc.HTTPMovedPermanently) as raised:
+    with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.with_trailing_slash(empty_func)()
     assert raised.exception.location == 'http://localhost/foo/bar/?foo=bar&baz=bam'
 
@@ -56,7 +53,7 @@ def test_with_trailing_slash_qs():
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar/'))
 def test_without_trailing_slash():
     patches.apply()
-    with assert_raises(webob.exc.HTTPMovedPermanently) as raised:
+    with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.without_trailing_slash(empty_func)()
     assert raised.exception.location == 'http://localhost/foo/bar'
 
@@ -71,6 +68,6 @@ def test_without_trailing_slash_ok():
 @patch.object(patches, 'request', webob.Request.blank('/foo/bar/?foo=bar&baz=bam'))
 def test_without_trailing_slash_qs():
     patches.apply()
-    with assert_raises(webob.exc.HTTPMovedPermanently) as raised:
+    with pytest.raises(webob.exc.HTTPMovedPermanently) as raised:
         tg.decorators.without_trailing_slash(empty_func)()
     assert raised.exception.location == 'http://localhost/foo/bar?foo=bar&baz=bam'
diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py
index cfe441693..49206ba64 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -23,16 +23,8 @@ from tg import tmpl_context as c
 from webob import Request, exc
 from bson import ObjectId
 from ming.orm.ormsession import ThreadLocalORMSession
-from alluratest.tools import (
-    assert_equals,
-    assert_equal,
-    assert_raises,
-    assert_is_none,
-    assert_is,
-    assert_true,
-    assert_false,
-)
 from mock import Mock, MagicMock, patch
+import pytest
 
 from allura import model as M
 from allura.lib import plugin
@@ -78,16 +70,16 @@ class TestProjectRegistrationProvider:
         v = self.provider.shortname_validator.to_python
 
         v('thisislegit', neighborhood=nbhd)
-        assert_raises(ProjectShortnameInvalid, v,
+        pytest.raises(ProjectShortnameInvalid, v,
                       'not valid', neighborhood=nbhd)
-        assert_raises(ProjectShortnameInvalid, v,
+        pytest.raises(ProjectShortnameInvalid, v,
                       'this-is-valid-but-too-long', neighborhood=nbhd)
-        assert_raises(ProjectShortnameInvalid, v,
+        pytest.raises(ProjectShortnameInvalid, v,
                       'this is invalid and too long', neighborhood=nbhd)
-        assert_raises(ProjectShortnameInvalid, v,
+        pytest.raises(ProjectShortnameInvalid, v,
                       'end-dash-', neighborhood=nbhd)
         Project.query.get.return_value = Mock()
-        assert_raises(ProjectConflict, v, 'thisislegit', neighborhood=nbhd)
+        pytest.raises(ProjectConflict, v, 'thisislegit', neighborhood=nbhd)
 
 
 @with_nose_compatibility
@@ -652,7 +644,7 @@ class TestLocalAuthenticationProvider:
         user.__ming__ = Mock()
         self.provider.validate_password = lambda u, p: False
         self.provider._encode_password = Mock()
-        assert_raises(
+        pytest.raises(
             exc.HTTPUnauthorized,
             self.provider.set_password, user, 'old', 'new')
         assert self.provider._encode_password.call_count == 0
diff --git a/Allura/allura/tests/test_security.py b/Allura/allura/tests/test_security.py
index f6771f3aa..fea9bc54d 100644
--- a/Allura/allura/tests/test_security.py
+++ b/Allura/allura/tests/test_security.py
@@ -16,7 +16,7 @@
 #       under the License.
 
 from tg import tmpl_context as c
-from alluratest.tools import assert_equal, assert_raises
+import pytest
 
 from ming.odm import ThreadLocalODMSession
 from allura.tests import decorators as td
@@ -51,7 +51,7 @@ def _add_to_group(user, role):
 
 @patch('allura.lib.security.requests.get', side_effect=Timeout())
 def test_check_breached_password(r_get):
-    with assert_raises(HIBPClientError):
+    with pytest.raises(HIBPClientError):
         HIBPClient.check_breached_password('qwerty')
 
 
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 4c22c1a93..5afc2c9b8 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -27,14 +27,9 @@ from ming.odm import session
 from bson import ObjectId
 from webob import Request
 from mock import Mock, patch
-from alluratest.tools import (
-    assert_equal,
-    assert_not_equal,
-    assert_raises,
-    assert_in,
-)
 from pygments import highlight
 from pygments.lexers import get_lexer_for_filename
+import pytest
 from tg import config
 import html5lib
 import html5lib.treewalkers
@@ -363,9 +358,9 @@ def test_empty_cursor():
     assert cursor.hint('index') == cursor
     assert cursor.extensions == []
     assert cursor.options(arg1='val1', arg2='val2') == cursor
-    assert_raises(ValueError, cursor.one)
-    assert_raises(StopIteration, cursor.next)
-    assert_raises(StopIteration, cursor._next_impl)
+    pytest.raises(ValueError, cursor.one)
+    pytest.raises(StopIteration, cursor.next)
+    pytest.raises(StopIteration, cursor._next_impl)
 
 
 def test_DateJSONEncoder():
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 3b11f5e05..c1eeaa0e8 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -21,12 +21,7 @@ import hashlib
 import datetime as dt
 
 from mock import Mock, MagicMock, patch, call
-from alluratest.tools import (
-    assert_raises,
-    assert_equal,
-    assert_not_in,
-    assert_in,
-)
+import pytest
 from datadiff import tools as dd
 from formencode import Invalid
 from ming.odm import session
@@ -100,10 +95,10 @@ class TestValidators(TestWebhookBase):
         app = self.git
         invalid_app = self.project.app_instance('src2')
         v = WebhookValidator(sender=sender, app=app, not_empty=True)
-        with assert_raises(Invalid) as cm:
+        with pytest.raises(Invalid) as cm:
             v.to_python(None)
         assert cm.exception.msg == 'Please enter a value'
-        with assert_raises(Invalid) as cm:
+        with pytest.raises(Invalid) as cm:
             v.to_python('invalid id')
         assert cm.exception.msg == 'Invalid webhook'
 
@@ -113,14 +108,14 @@ class TestValidators(TestWebhookBase):
                        secret='secret')
         session(wh).flush(wh)
         # invalid type
-        with assert_raises(Invalid) as cm:
+        with pytest.raises(Invalid) as cm:
             v.to_python(wh._id)
         assert cm.exception.msg == 'Invalid webhook'
 
         wh.type = 'repo-push'
         session(wh).flush(wh)
         # invalild app
-        with assert_raises(Invalid) as cm:
+        with pytest.raises(Invalid) as cm:
             v.to_python(wh._id)
         assert cm.exception.msg == 'Invalid webhook'
 
diff --git a/Allura/allura/tests/unit/spam/test_akismet.py b/Allura/allura/tests/unit/spam/test_akismet.py
index 2c6e2af31..384ce1b32 100644
--- a/Allura/allura/tests/unit/spam/test_akismet.py
+++ b/Allura/allura/tests/unit/spam/test_akismet.py
@@ -34,7 +34,7 @@ from alluratest.pytest_helpers import with_nose_compatibility
 class TestAkismet(unittest.TestCase):
 
     @mock.patch('allura.lib.spam.akismetfilter.akismet')
-    def setUp(self, akismet_lib):
+    def setup_method(self, method, akismet_lib):
         self.akismet = AkismetSpamFilter({'spam.key': 'example', 'base_url': 'http://localhost/'})
 
         def side_effect(*args, **kw):
diff --git a/Allura/allura/tests/unit/test_helpers/test_set_context.py b/Allura/allura/tests/unit/test_helpers/test_set_context.py
index 9e6999231..68b8898e4 100644
--- a/Allura/allura/tests/unit/test_helpers/test_set_context.py
+++ b/Allura/allura/tests/unit/test_helpers/test_set_context.py
@@ -15,7 +15,7 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from alluratest.tools import assert_raises
+import pytest
 from tg import tmpl_context as c
 from bson import ObjectId
 
@@ -101,14 +101,14 @@ class TestWhenProjectIsNotFound(WithDatabase):
 
     def test_that_it_raises_an_exception(self):
         nbhd = create_neighborhood()
-        assert_raises(NoSuchProjectError,
+        pytest.raises(NoSuchProjectError,
                       set_context,
                       'myproject',
                       neighborhood=nbhd)
 
     def test_proper_exception_when_id_lookup(self):
         create_neighborhood()
-        assert_raises(NoSuchProjectError,
+        pytest.raises(NoSuchProjectError,
                       set_context,
                       ObjectId(),
                       neighborhood=None)
@@ -118,7 +118,7 @@ class TestWhenProjectIsNotFound(WithDatabase):
 class TestWhenNeighborhoodIsNotFound(WithDatabase):
 
     def test_that_it_raises_an_exception(self):
-        assert_raises(NoSuchNeighborhoodError,
+        pytest.raises(NoSuchNeighborhoodError,
                       set_context,
                       'myproject',
                       neighborhood='myneighborhood')
diff --git a/Allura/allura/tests/unit/test_package_path_loader.py b/Allura/allura/tests/unit/test_package_path_loader.py
index 5aec5fea2..5e3702715 100644
--- a/Allura/allura/tests/unit/test_package_path_loader.py
+++ b/Allura/allura/tests/unit/test_package_path_loader.py
@@ -20,8 +20,8 @@ from collections import OrderedDict
 from unittest import TestCase
 
 import jinja2
-from alluratest.tools import assert_equal, assert_raises
 import mock
+import pytest
 from tg import config
 
 from allura.lib.package_path_loader import PackagePathLoader
@@ -81,7 +81,7 @@ class TestPackagePathLoader(TestCase):
         for ep in eps:
             ep.name = ep.ep_name
             ep.load.return_value.template_path_rules = ep.rules
-        assert_raises(jinja2.TemplateError, PackagePathLoader()._load_rules)
+        pytest.raises(jinja2.TemplateError, PackagePathLoader()._load_rules)
 
     def test_replace_signposts(self):
         ppl = PackagePathLoader()
@@ -219,14 +219,14 @@ class TestPackagePathLoader(TestCase):
         ppl.init_paths = mock.Mock()
         fs_loader().get_source.side_effect = jinja2.TemplateNotFound('test')
 
-        assert_raises(
+        pytest.raises(
             jinja2.TemplateError,
             ppl.get_source, 'env', 'allura.ext.admin:templates/audit.html')
         assert fs_loader().get_source.call_count == 1
         fs_loader().get_source.reset_mock()
 
         with mock.patch.dict(config, {'disable_template_overrides': False}):
-            assert_raises(
+            pytest.raises(
                 jinja2.TemplateError,
                 ppl.get_source, 'env', 'allura.ext.admin:templates/audit.html')
             assert fs_loader().get_source.call_count == 2
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_rest.py b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
index d20166d5f..5ee7b6b0b 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_rest.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_rest.py
@@ -23,13 +23,13 @@ from alluratest.controller import TestRestApiBase
 
 class TestActivityHasAccessAPI(TestRestApiBase):
 
-    def setUp(self, *args, **kwargs):
-        super().setUp(*args, **kwargs)
+    def setup_method(self, method, *args, **kwargs):
+        super().setup_method(method, *args, **kwargs)
         self._enabled = config.get('activitystream.enabled', 'false')
         config['activitystream.enabled'] = 'true'
 
-    def tearDown(self, *args, **kwargs):
-        super().tearDown(*args, **kwargs)
+    def teardown_method(self, method, *args, **kwargs):
+        super().teardown_method(method, *args, **kwargs)
         config['activitystream.enabled'] = self._enabled
 
     def test_has_access_no_params(self):
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_root.py b/ForgeActivity/forgeactivity/tests/functional/test_root.py
index cb90360d1..565576e05 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -33,13 +33,13 @@ from allura.tests import decorators as td
 
 class TestActivityController(TestController):
 
-    def setUp(self, *args, **kwargs):
-        super().setUp(*args, **kwargs)
+    def setup_method(self, method, *args, **kwargs):
+        super().setup_method(method, *args, **kwargs)
         self._enabled = config.get('activitystream.enabled', 'false')
         config['activitystream.enabled'] = 'true'
 
-    def tearDown(self, *args, **kwargs):
-        super().tearDown(*args, **kwargs)
+    def teardown_method(self, method, *args, **kwargs):
+        super().teardown_method(method, *args, **kwargs)
         config['activitystream.enabled'] = self._enabled
 
     def test_index(self):
diff --git a/ForgeBlog/forgeblog/tests/functional/test_rest.py b/ForgeBlog/forgeblog/tests/functional/test_rest.py
index 9e8a87756..068a5e911 100644
--- a/ForgeBlog/forgeblog/tests/functional/test_rest.py
+++ b/ForgeBlog/forgeblog/tests/functional/test_rest.py
@@ -29,8 +29,8 @@ from forgeblog import model as BM
 
 class TestBlogApi(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_tool('test', 'Blog', 'blog')
diff --git a/ForgeBlog/forgeblog/tests/test_app.py b/ForgeBlog/forgeblog/tests/test_app.py
index bb224a057..c61b0a0e8 100644
--- a/ForgeBlog/forgeblog/tests/test_app.py
+++ b/ForgeBlog/forgeblog/tests/test_app.py
@@ -34,7 +34,7 @@ from forgeblog import model as BM
 
 class TestApp:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
 
     @td.with_tool('test', 'Blog', 'blog')
@@ -75,7 +75,7 @@ class TestApp:
 
 class TestBulkExport:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_global_objects()
 
diff --git a/ForgeBlog/forgeblog/tests/test_commands.py b/ForgeBlog/forgeblog/tests/test_commands.py
index b1aa45196..3b82d6801 100644
--- a/ForgeBlog/forgeblog/tests/test_commands.py
+++ b/ForgeBlog/forgeblog/tests/test_commands.py
@@ -34,7 +34,7 @@ test_config = pkg_resources.resource_filename(
     'allura', '../test.ini') + '#main'
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_global_objects()
 
diff --git a/ForgeBlog/forgeblog/tests/test_roles.py b/ForgeBlog/forgeblog/tests/test_roles.py
index 3fe6a64df..18403dce9 100644
--- a/ForgeBlog/forgeblog/tests/test_roles.py
+++ b/ForgeBlog/forgeblog/tests/test_roles.py
@@ -23,7 +23,7 @@ from allura.lib import security
 from allura.lib import helpers as h
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_global_objects()
     h.set_context('test', neighborhood='Projects')
diff --git a/ForgeBlog/forgeblog/tests/unit/__init__.py b/ForgeBlog/forgeblog/tests/unit/__init__.py
index 202091598..648c054e8 100644
--- a/ForgeBlog/forgeblog/tests/unit/__init__.py
+++ b/ForgeBlog/forgeblog/tests/unit/__init__.py
@@ -31,7 +31,7 @@ def setUp():
 
 class BlogTestWithModel:
 
-    def setUp(self):
+    def setup_method(self, method):
         bootstrap.wipe_database()
         project_reg = plugin.ProjectRegistrationProvider.get()
         c.user = bootstrap.create_user('Test User')
@@ -46,5 +46,5 @@ class BlogTestWithModel:
         ThreadLocalORMSession.flush_all()
         h.set_context('test', 'blog', neighborhood='Projects')
 
-    def tearDown(self):
+    def teardown_method(self, method):
         ThreadLocalORMSession.close_all()
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index a20cb16e9..cfc2f5c84 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 import mock
+import pytest
 import random
 import logging
 from six.moves.email_mime_text import MIMEText
@@ -30,7 +31,6 @@ from ming.odm import ThreadLocalORMSession
 from tg import tmpl_context as c
 from tg import config
 
-from alluratest.tools import assert_equal, assert_in, assert_not_in, assert_true, assert_false, assert_raises
 import feedparser
 
 from allura import model as M
@@ -45,8 +45,8 @@ log = logging.getLogger(__name__)
 
 
 class TestForumEmail(TestController):
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         c.user = M.User.by_username('test-admin')
         self.app.get('/discussion/')
         r = self.app.get('/admin/discussion/forums')
@@ -136,8 +136,8 @@ class TestForumMessageHandling(TestController):
     Tests all the "handle_message" related logic, which is what inbound emails run through
     '''
 
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         self.app.get('/discussion/')
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
@@ -302,8 +302,8 @@ class TestForumMessageHandling(TestController):
 
 
 class TestForum(TestController):
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         self.app.get('/discussion/')
         r = self.app.get('/admin/discussion/forums')
         form = r.forms['add-forum']
@@ -496,7 +496,7 @@ class TestForum(TestController):
             self.test_posting()
 
             # second should fail
-            with assert_raises(Exception):
+            with pytest.raises(Exception):
                 self.test_posting()
 
     def test_notifications_escaping(self):
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
index 19babaca5..22fea58a3 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py
@@ -29,8 +29,8 @@ log = logging.getLogger(__name__)
 
 class TestForumAdmin(TestController):
 
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         self.app.get('/discussion/')
 
     def test_forum_CRUD(self):
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
index ff7449d1e..1219d2a87 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_import.py
@@ -31,8 +31,8 @@ from alluratest.controller import TestRestApiBase
 
 class TestImportController(TestRestApiBase):  # TestController):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         here_dir = os.path.dirname(__file__)
         self.app.get('/discussion/')
         self.json_text = open(here_dir + '/data/sf.json').read()
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
index b20d610a2..cebce6467 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_rest.py
@@ -15,8 +15,6 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from alluratest.tools import assert_equal, assert_in
-
 from allura.lib import helpers as h
 from allura.tests import decorators as td
 from allura import model as M
@@ -27,8 +25,8 @@ from ming.orm import ThreadLocalORMSession
 
 class TestDiscussionApiBase(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_discussion
diff --git a/ForgeDiscussion/forgediscussion/tests/test_app.py b/ForgeDiscussion/forgediscussion/tests/test_app.py
index bb0b8d64b..0bf49aeca 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_app.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_app.py
@@ -53,7 +53,7 @@ class TestApp(TestDiscussionApiBase):  # creates some sample data
 
 class TestAppSitemap:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_unit_test()
         self.user = M.User.query.get(username='root')
diff --git a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
index 4bc0eef66..f05c6d993 100644
--- a/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
+++ b/ForgeDiscussion/forgediscussion/tests/test_forum_roles.py
@@ -23,7 +23,7 @@ from allura.lib import security
 from allura.tests import decorators as td
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_global_objects()
 
diff --git a/ForgeFeedback/forgefeedback/tests/functional/test_root.py b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
index 37866f797..69243f0d5 100644
--- a/ForgeFeedback/forgefeedback/tests/functional/test_root.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -17,9 +17,6 @@
 from tg import tmpl_context as c
 from tg import config
 
-from alluratest.tools import assert_equal, assert_in, assert_not_in
-from alluratest.tools import assert_true, assert_false, assert_raises
-
 from allura import model as M
 from alluratest.controller import TestController
 from allura.lib import helpers as h
@@ -30,9 +27,6 @@ from forgefeedback import model as FM
 
 class TestFeedback(TestController):
 
-    def setUp(self):
-        TestController.setUp(self)
-
     def test_feedback(self):
         c.user = M.User.by_username('test-admin')
         self.app.get('/feedback/')
diff --git a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
index 39ba76c70..64b626290 100644
--- a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -26,7 +26,7 @@ from allura.tests import decorators as td
 from allura.lib import helpers as h
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_with_tools()
 
diff --git a/ForgeFeedback/forgefeedback/tests/unit/__init__.py b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
index b658fcab8..1bd8052c5 100644
--- a/ForgeFeedback/forgefeedback/tests/unit/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
@@ -31,7 +31,7 @@ def setUp():
 
 class FeedbackTestWithModel:
 
-    def setUp(self):
+    def setup_method(self, method):
         bootstrap.wipe_database()
         project_reg = plugin.ProjectRegistrationProvider.get()
         c.user = bootstrap.create_user('Test User')
@@ -46,5 +46,5 @@ class FeedbackTestWithModel:
         ThreadLocalORMSession.flush_all()
         h.set_context('test', 'feedback', neighborhood='Projects')
 
-    def tearDown(self):
+    def teardown_method(self, method):
         ThreadLocalORMSession.close_all()
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
index d636594a8..f6b2b0ca8 100644
--- a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -33,8 +33,8 @@ from forgefeedback import feedback_main
 
 class TestFeedbackApp(FeedbackTestWithModel):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         c.user = User(username='test-user')
         h.set_context('test', 'feedback', neighborhood='Projects')
 
diff --git a/ForgeFiles/forgefiles/tests/functional/test_root.py b/ForgeFiles/forgefiles/tests/functional/test_root.py
index 999fd5367..5c44760f1 100644
--- a/ForgeFiles/forgefiles/tests/functional/test_root.py
+++ b/ForgeFiles/forgefiles/tests/functional/test_root.py
@@ -28,9 +28,6 @@ from testfixtures import TempDirectory
 
 
 class TestFiles(TestController):
-    def setUp(self):
-        TestController.setUp(self)
-
     def test_files(self):
         c.user = M.User.by_username('test-admin')
         r = self.app.get('/files/')
diff --git a/ForgeFiles/forgefiles/tests/model/__init__.py b/ForgeFiles/forgefiles/tests/model/__init__.py
index 9def3d957..72fc7a79b 100644
--- a/ForgeFiles/forgefiles/tests/model/__init__.py
+++ b/ForgeFiles/forgefiles/tests/model/__init__.py
@@ -31,7 +31,7 @@ def setUp():
 
 class FilesTestWithModel:
 
-    def setUp(self):
+    def setup_method(self, method):
         bootstrap.wipe_database()
         project_reg = plugin.ProjectRegistrationProvider.get()
         c.user = bootstrap.create_user('Test User')
@@ -46,6 +46,6 @@ class FilesTestWithModel:
         ThreadLocalORMSession.flush_all()
         h.set_context('test', 'files', neighborhood='Projects')
 
-    def tearDown(self):
+    def teardown_method(self, method):
         ThreadLocalORMSession.close_all()
 
diff --git a/ForgeFiles/forgefiles/tests/test_files_roles.py b/ForgeFiles/forgefiles/tests/test_files_roles.py
index 2675a3e51..6df1ae701 100644
--- a/ForgeFiles/forgefiles/tests/test_files_roles.py
+++ b/ForgeFiles/forgefiles/tests/test_files_roles.py
@@ -25,7 +25,7 @@ from allura.tests import decorators as td
 from allura.lib import helpers as h
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_with_tools()
 
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index cabeb2b0c..c681d5bbd 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -44,8 +44,8 @@ import six
 
 
 class _TestCase(TestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -78,8 +78,8 @@ class _TestCase(TestController):
 
 
 class TestUIController(TestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -570,8 +570,8 @@ class TestRestController(_TestCase):
 
 
 class TestHasAccessAPI(TestRestApiBase):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -620,8 +620,8 @@ class TestHasAccessAPI(TestRestApiBase):
 
 
 class TestFork(_TestCase):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         to_project = M.Project.query.get(
             shortname='test2', neighborhood_id=c.project.neighborhood_id)
         r = self.app.post('/src-git/fork', params=dict(
@@ -969,8 +969,8 @@ class TestFork(_TestCase):
 
 
 class TestDiff(TestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -998,8 +998,8 @@ class TestDiff(TestController):
 
 
 class TestGitRename(TestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -1066,8 +1066,8 @@ class TestGitRename(TestController):
 
 
 class TestGitBranch(TestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_git
@@ -1121,8 +1121,8 @@ class TestGitBranch(TestController):
 
 
 class TestIncludeMacro(_TestCase):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         setup_global_objects()
 
     def test_parse_repo(self):
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index bb687b91b..7d29d7451 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -48,7 +48,7 @@ from forgewiki import model as WM
 
 class TestNewGit(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -126,7 +126,7 @@ class TestNewGit(unittest.TestCase):
 
 class TestGitRepo(unittest.TestCase, RepoImplTestBase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -373,7 +373,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         self.assertEqual(new_tree.other_ids, orig_tree.other_ids)
 
     def test_refresh(self):
-        # test results of things that ran during setUp
+        # test results of things that ran during setup_method
         notification = M.Notification.query.find({'subject': '[test:src-git] 5 new commits to Git'}).first()
         assert notification
         domain = '.'.join(reversed(c.app.url[1:-1].split('/'))).replace('_', '-')
@@ -1026,7 +1026,7 @@ class TestGitImplementation(unittest.TestCase):
 
 class TestGitCommit(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -1102,7 +1102,7 @@ class TestGitCommit(unittest.TestCase):
 
 class TestGitHtmlView(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -1133,7 +1133,7 @@ class TestGitHtmlView(unittest.TestCase):
 
 class TestGitRename(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
diff --git a/ForgeGit/forgegit/tests/test_git_app.py b/ForgeGit/forgegit/tests/test_git_app.py
index 823004c40..c4868448a 100644
--- a/ForgeGit/forgegit/tests/test_git_app.py
+++ b/ForgeGit/forgegit/tests/test_git_app.py
@@ -28,7 +28,7 @@ from forgegit.tests import with_git
 
 class TestGitApp(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
diff --git a/ForgeGit/forgegit/tests/test_tasks.py b/ForgeGit/forgegit/tests/test_tasks.py
index 7a8921435..26e22c644 100644
--- a/ForgeGit/forgegit/tests/test_tasks.py
+++ b/ForgeGit/forgegit/tests/test_tasks.py
@@ -34,7 +34,7 @@ from forgegit.tests.functional.test_controllers import _TestCase as GitRealDataB
 
 class TestGitTasks(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -69,8 +69,8 @@ class TestCoreAlluraTasks(GitRealDataBaseTestCase):
     Not git-specific things we are testing, but the git tool is a useful standard repo type to use for it
     """
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     def test_refreshrepo(self):
diff --git a/ForgeImporters/forgeimporters/github/tests/test_code.py b/ForgeImporters/forgeimporters/github/tests/test_code.py
index d86d16031..d2ba20a20 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_code.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_code.py
@@ -35,7 +35,7 @@ with_git = with_tool(test_project_with_repo, 'git', 'src', 'git')
 
 class TestGitHubRepoImporter(TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_unit_test()
 
     def _make_project(self, gh_proj_name=None):
diff --git a/ForgeImporters/forgeimporters/github/tests/test_oauth.py b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
index 1e02d83e0..c8bbadf99 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_oauth.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_oauth.py
@@ -27,8 +27,8 @@ from forgeimporters.github import GitHubOAuthMixin
 
 class TestGitHubOAuthMixin(TestController, TestCase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         setup_unit_test()
         c.user = Mock()
         self.mix = GitHubOAuthMixin()
diff --git a/ForgeImporters/forgeimporters/github/tests/test_utils.py b/ForgeImporters/forgeimporters/github/tests/test_utils.py
index 5e47bcefe..5f067e8bc 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_utils.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_utils.py
@@ -22,7 +22,7 @@ from forgeimporters.github.utils import GitHubMarkdownConverter
 
 class TestGitHubMarkdownConverter:
 
-    def setUp(self):
+    def setup_method(self, method):
         self.conv = GitHubMarkdownConverter('user', 'project')
 
     def test_convert_sha(self):
diff --git a/ForgeImporters/forgeimporters/github/tests/test_wiki.py b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
index 5afcebb17..20f01002b 100644
--- a/ForgeImporters/forgeimporters/github/tests/test_wiki.py
+++ b/ForgeImporters/forgeimporters/github/tests/test_wiki.py
@@ -74,7 +74,7 @@ class TestGitHubWikiImporter(TestCase):
                 project=p, user=u, url='foo')
             g.post_event.assert_called_once_with('project_updated')
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.blob1 = Mock()
         self.blob1.name = 'Home.md'
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_discussion.py b/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
index 5fd08d631..01788aab1 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_discussion.py
@@ -33,14 +33,11 @@ from forgediscussion import utils
 
 class TestDiscussionImporter(TestCase):
 
-    def setUp(self):
-        super().setUp()
-
+    def setup_method(self, method):
         self.patcher_g = mock.patch('forgeimporters.base.g', mock.MagicMock())
         self.patcher_g.start()
 
-    def tearDown(self):
-        super().tearDown()
+    def teardown_method(self, method):
         self.patcher_g.stop()
 
     @mock.patch.object(discussion, 'c')
@@ -1273,8 +1270,8 @@ class TestDiscussionImporter(TestCase):
 
 class TestForgeDiscussionController(TestController, TestCase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
 
     @with_discussion
     def test_index(self):
diff --git a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
index 9e8277099..f1c5b1aca 100644
--- a/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/forge/test_tracker.py
@@ -33,14 +33,12 @@ from forgeimporters.forge import alluraImporter
 
 class TestTrackerImporter(TestCase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
         # every single test method here creates an importer and ToolImporterMeta uses 'g'
         self.patcher_g = mock.patch('forgeimporters.base.g', mock.MagicMock())
         self.patcher_g.start()
 
-    def tearDown(self):
-        super().tearDown()
+    def teardown_method(self, method):
         self.patcher_g.stop()
 
     @mock.patch.object(tracker, 'File')
@@ -338,9 +336,9 @@ class TestTrackerImporter(TestCase):
 
 class TestForgeTrackerImportController(TestController, TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         """Mount Allura importer on the Tracker admin controller"""
-        super().setUp()
+        super().setup_method(method)
         from forgetracker.tracker_main import TrackerAdminController
         TrackerAdminController._importer = \
                 tracker.ForgeTrackerImportController(tracker.ForgeTrackerImporter())
diff --git a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
index 78dd617bf..7945bb209 100644
--- a/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
+++ b/ForgeImporters/forgeimporters/tests/github/functional/test_github.py
@@ -47,8 +47,8 @@ class TestGitHubImportController(TestController, TestCase):
 
 class TestGitHubOAuth(TestController):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         tg.config['github_importer.client_id'] = 'client_id'
         tg.config['github_importer.client_secret'] = 'secret'
 
diff --git a/ForgeImporters/forgeimporters/tests/github/test_extractor.py b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
index 0d890c6e4..3edac5eb3 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_extractor.py
@@ -84,7 +84,7 @@ class TestGitHubProjectExtractor(TestCase):
         response.info = lambda: headers
         return response
 
-    def setUp(self):
+    def setup_method(self, method):
         self.extractor = github.GitHubProjectExtractor('test_project')
         self.extractor.urlopen = self.mocked_urlopen
 
diff --git a/ForgeImporters/forgeimporters/tests/github/test_tracker.py b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
index 2219295cf..e06fcb3e1 100644
--- a/ForgeImporters/forgeimporters/tests/github/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/github/test_tracker.py
@@ -27,14 +27,12 @@ from forgeimporters.github.utils import GitHubMarkdownConverter
 
 class TestTrackerImporter(TestCase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
         # every single test method here creates an importer and ToolImporterMeta uses 'g'
         self.patcher_g = mock.patch('forgeimporters.base.g', mock.MagicMock())
         self.patcher_g.start()
 
-    def tearDown(self):
-        super().tearDown()
+    def teardown_method(self, method):
         self.patcher_g.stop()
 
     @mock.patch.object(tracker, 'g')
diff --git a/ForgeImporters/forgeimporters/tests/test_base.py b/ForgeImporters/forgeimporters/tests/test_base.py
index b5d6dbe74..fe3d18d36 100644
--- a/ForgeImporters/forgeimporters/tests/test_base.py
+++ b/ForgeImporters/forgeimporters/tests/test_base.py
@@ -20,8 +20,8 @@ import errno
 
 from formencode import Invalid
 import mock
+import pytest
 from tg import expose, config
-from alluratest.tools import assert_equal, assert_raises
 from webob.exc import HTTPUnauthorized
 
 from alluratest.controller import TestController, setup_basic_test
@@ -89,7 +89,7 @@ def test_import_tool_failed(g, ToolImporter, format_exc):
     importer.import_tool.side_effect = RuntimeError('my error')
     ToolImporter.return_value = importer
 
-    with assert_raises(RuntimeError):
+    with pytest.raises(RuntimeError):
         base.import_tool('forgeimporters.base.ToolImporter', project_name='project_name')
     g.post_event.assert_called_once_with(
         'import_tool_task_failed',
@@ -248,7 +248,7 @@ class TestToolImporter(TestCase):
 
 class TestToolsValidator(TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         self.tv = base.ToolsValidator('good-source')
 
     @mock.patch.object(base.ToolImporter, 'by_name')
@@ -372,8 +372,8 @@ def test_save_importer_upload(giup, os):
         fp.write.assert_called_once_with('data')
 
     os.makedirs.side_effect = OSError(errno.EACCES, 'foo')
-    assert_raises(OSError, base.save_importer_upload,
-                  'project', 'file', 'data')
+    with pytest.raises(OSError):
+        base.save_importer_upload('project', 'file', 'data')
 
 
 class TestFile:
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 07a524efc..1789654d7 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -40,7 +40,7 @@ from forgeimporters.trac.tickets import (
 
 class TestTracTicketImporter(TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_unit_test()
 
     @patch('forgeimporters.trac.tickets.session')
@@ -110,9 +110,9 @@ class TestTracTicketImporter(TestCase):
 
 class TestTracTicketImportController(TestController, TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         """Mount Trac import controller on the Tracker admin controller"""
-        super().setUp()
+        super().setup_method(method)
         from forgetracker.tracker_main import TrackerAdminController
         self.importer = TrackerAdminController._importer = TracTicketImportController(TracTicketImporter())
 
diff --git a/ForgeLink/forgelink/tests/functional/test_rest.py b/ForgeLink/forgelink/tests/functional/test_rest.py
index d420d537a..6b3e026d9 100644
--- a/ForgeLink/forgelink/tests/functional/test_rest.py
+++ b/ForgeLink/forgelink/tests/functional/test_rest.py
@@ -24,8 +24,8 @@ from allura.lib import helpers as h
 
 class TestLinkApi(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_link
@@ -80,8 +80,8 @@ class TestLinkApi(TestRestApiBase):
 
 class TestLinkHasAccess(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_link
diff --git a/ForgeLink/forgelink/tests/test_app.py b/ForgeLink/forgelink/tests/test_app.py
index 28efa0054..d6e2fb4a6 100644
--- a/ForgeLink/forgelink/tests/test_app.py
+++ b/ForgeLink/forgelink/tests/test_app.py
@@ -28,7 +28,7 @@ from alluratest.controller import setup_basic_test
 
 class TestBulkExport:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
 
     @td.with_link
diff --git a/ForgeSVN/forgesvn/tests/functional/test_controllers.py b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
index 1a4cbe637..27b58e047 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -38,8 +38,8 @@ from allura.tests.decorators import with_tool
 
 class SVNTestController(TestController):
 
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     def _make_app(self, mount_point, name):
@@ -351,8 +351,8 @@ class TestImportController(SVNTestController):
 
 class SVNTestRenames(TestController):
 
-    def setUp(self):
-        TestController.setUp(self)
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @with_svn
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 9d5e02856..885aaaff1 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -53,7 +53,7 @@ import six
 
 class TestNewRepo(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -107,7 +107,7 @@ class TestNewRepo(unittest.TestCase):
 
 class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -573,7 +573,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
 
 class TestSVNRev(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -687,7 +687,7 @@ class _Test(unittest.TestCase):
     def _make_log(self, ci):
         session(ci).flush(ci)
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_global_objects()
         ThreadLocalORMSession.flush_all()
@@ -697,8 +697,8 @@ class _Test(unittest.TestCase):
 
 class _TestWithRepo(_Test):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         h.set_context('test', neighborhood='Projects')
         c.project.install_app('svn', 'test1')
         h.set_context('test', 'test1', neighborhood='Projects')
@@ -716,8 +716,8 @@ class _TestWithRepo(_Test):
 
 class _TestWithRepoAndCommit(_TestWithRepo):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.ci, isnew = self._make_commit('foo')
         ThreadLocalORMSession.flush_all()
         # ThreadLocalORMSession.close_all()
@@ -880,8 +880,8 @@ class TestRepoObject(_TestWithRepoAndCommit):
 
 class TestCommit(_TestWithRepo):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.ci, isnew = self._make_commit(
             'foo',
             a=dict(
@@ -1022,7 +1022,7 @@ class TestCommit(_TestWithRepo):
 
 class TestRename(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
@@ -1058,7 +1058,7 @@ class TestRename(unittest.TestCase):
 
 class TestDirectRepoAccess:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
diff --git a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
index 0667d1fdc..0313e822b 100644
--- a/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
+++ b/ForgeSVN/forgesvn/tests/model/test_svnimplementation.py
@@ -26,7 +26,7 @@ from forgesvn.model.svn import SVNImplementation
 
 class TestSVNImplementation:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_unit_test()
 
     def test_compute_tree_new(self):
diff --git a/ForgeSVN/forgesvn/tests/test_svn_app.py b/ForgeSVN/forgesvn/tests/test_svn_app.py
index 605ffe59c..d5c8770c1 100644
--- a/ForgeSVN/forgesvn/tests/test_svn_app.py
+++ b/ForgeSVN/forgesvn/tests/test_svn_app.py
@@ -28,7 +28,7 @@ from forgesvn.tests import with_svn
 
 class TestSVNApp(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
 
diff --git a/ForgeSVN/forgesvn/tests/test_tasks.py b/ForgeSVN/forgesvn/tests/test_tasks.py
index e95899ecf..b3e388e98 100644
--- a/ForgeSVN/forgesvn/tests/test_tasks.py
+++ b/ForgeSVN/forgesvn/tests/test_tasks.py
@@ -36,14 +36,14 @@ from forgesvn.tests import with_svn
 
 class TestRepoTasks(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         self.setup_with_tools()
         if asbool(tg.config.get('smtp.mock')):
             self.smtp_mock = mock.patch('allura.lib.mail_util.smtplib.SMTP')
             self.smtp_mock.start()
 
-    def tearDown(self):
+    def teardown_method(self, method):
         if asbool(tg.config.get('smtp.mock')):
             self.smtp_mock.stop()
 
diff --git a/ForgeShortUrl/forgeshorturl/tests/functional/test.py b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
index 547ca8e01..1d3471d06 100644
--- a/ForgeShortUrl/forgeshorturl/tests/functional/test.py
+++ b/ForgeShortUrl/forgeshorturl/tests/functional/test.py
@@ -29,8 +29,8 @@ from forgeshorturl.model import ShortUrl
 
 class TestRootController(TestController):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_url
diff --git a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
index 9074e46ff..cba1fc793 100644
--- a/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
+++ b/ForgeTracker/forgetracker/tests/command/test_fix_discussion.py
@@ -30,7 +30,7 @@ test_config = pkg_resources.resource_filename(
     'allura', '../test.ini') + '#main'
 
 
-def setUp(self):
+def setup_method(self, method):
     """Method called by nose before running each test"""
     setup_basic_test()
     setup_global_objects()
diff --git a/ForgeTracker/forgetracker/tests/functional/test_rest.py b/ForgeTracker/forgetracker/tests/functional/test_rest.py
index be72dd250..7db63dfa2 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -32,8 +32,8 @@ from forgetracker import model as TM
 
 class TestTrackerApiBase(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_tool('test', 'Tickets', 'bugs',
@@ -101,8 +101,8 @@ class TestRestNewTicket(TestTrackerApiBase):
 
 class TestRestUpdateTicket(TestTrackerApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         ticket_view = self.create_ticket()
         self.ticket_args = ticket_view.json['ticket']
 
@@ -124,8 +124,8 @@ class TestRestUpdateTicket(TestTrackerApiBase):
 
 class TestRestIndex(TestTrackerApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.create_ticket()
 
     def test_ticket_index(self):
@@ -169,8 +169,8 @@ class TestRestIndex(TestTrackerApiBase):
 
 class TestRestDiscussion(TestTrackerApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         ticket_view = self.create_ticket()
         self.ticket_args = ticket_view.json['ticket']
 
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index e0556322e..1b97a8b37 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -28,15 +28,6 @@ import mock
 import PIL
 from bs4 import BeautifulSoup
 from mock import patch
-from alluratest.tools import (
-    assert_true,
-    assert_false,
-    assert_equal,
-    assert_in,
-    assert_raises,
-    assert_not_in,
-    assert_not_equal,
-)
 from formencode.variabledecode import variable_encode
 from tg import tmpl_context as c
 from tg import app_globals as g
@@ -2753,9 +2744,10 @@ def post_install_hook(app):
 
 
 class TestEmailMonitoring(TrackerTestController):
-    def __init__(self):
-        super().__init__()
-        self.test_email = 'mailinglist@example.com'
+
+    @classmethod
+    def setup_class(cls):
+        cls.test_email = 'mailinglist@example.com'
 
     def _set_options(self, monitoring_type='AllTicketChanges'):
         r = self.app.post('/admin/bugs/set_options', params={
@@ -2887,8 +2879,8 @@ class TestEmailMonitoring(TrackerTestController):
 
 
 class TestCustomUserField(TrackerTestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         params = dict(
             custom_fields=[
                 dict(name='_code_review', label='Code Review', type='user',
@@ -3018,8 +3010,8 @@ class TestShowDefaultFields(TrackerTestController):
 
 
 class TestBulkMove(TrackerTestController):
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.new_ticket(summary='A New Hope')
         self.new_ticket(summary='The Empire Strikes Back')
         self.new_ticket(summary='Return Of The Jedi')
diff --git a/ForgeTracker/forgetracker/tests/test_app.py b/ForgeTracker/forgetracker/tests/test_app.py
index aed0fb60b..a688e8d01 100644
--- a/ForgeTracker/forgetracker/tests/test_app.py
+++ b/ForgeTracker/forgetracker/tests/test_app.py
@@ -38,7 +38,7 @@ from alluratest.pytest_helpers import with_nose_compatibility
 
 class TestApp:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
 
     @td.with_tracker
diff --git a/ForgeTracker/forgetracker/tests/test_tracker_roles.py b/ForgeTracker/forgetracker/tests/test_tracker_roles.py
index 242646c8f..086e2796f 100644
--- a/ForgeTracker/forgetracker/tests/test_tracker_roles.py
+++ b/ForgeTracker/forgetracker/tests/test_tracker_roles.py
@@ -23,7 +23,7 @@ from allura.lib import security
 from allura.tests import decorators as td
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_with_tools()
 
diff --git a/ForgeTracker/forgetracker/tests/unit/__init__.py b/ForgeTracker/forgetracker/tests/unit/__init__.py
index 1e9a0a9d4..3783fc20f 100644
--- a/ForgeTracker/forgetracker/tests/unit/__init__.py
+++ b/ForgeTracker/forgetracker/tests/unit/__init__.py
@@ -33,7 +33,7 @@ def setUp():
 
 class TrackerTestWithModel:
 
-    def setUp(self):
+    def setup_method(self, method):
         bootstrap.wipe_database()
         project_reg = plugin.ProjectRegistrationProvider.get()
         c.user = bootstrap.create_user('Test User')
@@ -49,5 +49,5 @@ class TrackerTestWithModel:
         h.set_context('test', 'bugs', neighborhood='Projects')
         tg.request_local.context.request = Request.blank('/')
 
-    def tearDown(self):
+    def teardown_method(self, method):
         ThreadLocalORMSession.close_all()
diff --git a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
index 6c063c8f8..bb22df47a 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_globals_model.py
@@ -30,8 +30,8 @@ from allura.lib import helpers as h
 
 class TestGlobalsModel(TrackerTestWithModel):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         c.project.install_app('Tickets', 'doc-bugs')
         ThreadLocalORMSession.flush_all()
 
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index 8051cde32..fd40593bc 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -32,16 +32,16 @@ from forgetracker import tracker_main
 
 class WithUserAndBugsApp(TrackerTestWithModel):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         c.user = User(username='test-user')
         h.set_context('test', 'bugs', neighborhood='Projects')
 
 
 class TestWhenSearchingWithCustomFields(WithUserAndBugsApp):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         with solr_search_returning_colors_are_wrong_ticket():
             self.response = tracker_main.RootController().search(q='friends')
 
@@ -57,8 +57,8 @@ class TestWhenSearchingWithCustomFields(WithUserAndBugsApp):
 
 class TestWhenLoadingFrontPage(WithUserAndBugsApp):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         with mongo_search_returning_colors_are_wrong_ticket():
             self.response = tracker_main.RootController().index()
 
diff --git a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
index 02744756b..940525363 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_ticket_model.py
@@ -22,16 +22,10 @@ import six.moves.urllib.request
 import six.moves.urllib.error
 
 import mock
+import pytest
 from ming.orm.ormsession import ThreadLocalORMSession
 from ming.orm import session
 from ming import schema
-from alluratest.tools import (
-    raises,
-    assert_equal,
-    assert_in,
-    assert_true,
-    assert_false,
-)
 from forgetracker.model import Ticket, TicketAttachment
 from forgetracker.tests.unit import TrackerTestWithModel
 from forgetracker.import_support import ResettableStream
@@ -76,9 +70,9 @@ class TestTicketModel(TrackerTestWithModel):
         ticket = Ticket.query.get(summary='my ticket')
         assert ticket.custom_fields == dict(my_field='my value')
 
-    @raises(schema.Invalid)
     def test_ticket_num_required(self):
-        Ticket(summary='my ticket')
+        with pytest.raises(schema.Invalid):
+            Ticket(summary='my ticket')
 
     def test_ticket_num_required2(self):
         t = Ticket(summary='my ticket', ticket_num=12)
diff --git a/ForgeUserStats/forgeuserstats/tests/test_model.py b/ForgeUserStats/forgeuserstats/tests/test_model.py
index 0d7bcba56..1a7720a11 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_model.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_model.py
@@ -38,7 +38,7 @@ with_git = td.with_tool('test', 'Git', 'git-userstats-model', 'Git', type='git')
 
 class TestUserStats(unittest.TestCase):
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_global_objects()
         self.user = User.by_username('test-user-2')
diff --git a/ForgeUserStats/forgeuserstats/tests/test_stats.py b/ForgeUserStats/forgeuserstats/tests/test_stats.py
index b36112658..cf206201b 100644
--- a/ForgeUserStats/forgeuserstats/tests/test_stats.py
+++ b/ForgeUserStats/forgeuserstats/tests/test_stats.py
@@ -31,8 +31,8 @@ from forgetracker import model as TM
 
 class TestStats(TestController):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         p = M.Project.query.get(shortname='test')
         p.add_user(M.User.by_username('test-user'), ['Admin'])
 
@@ -185,8 +185,8 @@ class TestStats(TestController):
 
 class TestGitCommit(TestController, unittest.TestCase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         setup_basic_test()
 
         user = User.by_username('test-admin')
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 694275746..4eb87d999 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -29,8 +29,8 @@ from forgewiki.model import Page
 
 class TestWikiApi(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_wiki
@@ -121,8 +121,8 @@ class TestWikiApi(TestRestApiBase):
 
 class TestWikiHasAccess(TestRestApiBase):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_wiki
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 05e2b181e..927f17dc4 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -37,8 +37,8 @@ from unittest.mock import MagicMock
 
 class TestRootController(TestController):
 
-    def setUp(self):
-        super().setUp()
+    def setup_method(self, method):
+        super().setup_method(method)
         self.setup_with_tools()
 
     @td.with_wiki
diff --git a/ForgeWiki/forgewiki/tests/test_app.py b/ForgeWiki/forgewiki/tests/test_app.py
index 3dc723c68..58159df5e 100644
--- a/ForgeWiki/forgewiki/tests/test_app.py
+++ b/ForgeWiki/forgewiki/tests/test_app.py
@@ -34,7 +34,7 @@ from forgewiki import model as WM
 
 class TestBulkExport:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_global_objects()
         self.setup_with_tools()
@@ -126,7 +126,7 @@ class TestBulkExport:
 
 class TestApp:
 
-    def setUp(self):
+    def setup_method(self, method):
         setup_basic_test()
         setup_global_objects()
         self.setup_with_tools()
diff --git a/ForgeWiki/forgewiki/tests/test_wiki_roles.py b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
index e03880976..f42f76618 100644
--- a/ForgeWiki/forgewiki/tests/test_wiki_roles.py
+++ b/ForgeWiki/forgewiki/tests/test_wiki_roles.py
@@ -25,7 +25,7 @@ from allura.lib import security
 from allura.tests import decorators as td
 
 
-def setUp():
+def setup_module(module):
     setup_basic_test()
     setup_with_tools()
 
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index 711a21daa..4c567b7df 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -70,7 +70,7 @@ def main(args):
                         debug_html=args.debug_html)
     print(json.dumps(counts))
     write_csv(counts, args.id, args.data_file)
-    test.tearDown()
+    test.teardown_method(method)
 
 
 def setup(test):
@@ -79,7 +79,7 @@ def setup(test):
                                   'stats.debug_line_length': 1000,
                                   }), \
             patch('timermiddleware.log.isEnabledFor', return_value=True):  # can't set this via logging configuration since setUp() will load a logging config and then start using it before we have a good place to tweak it
-        test.setUp()
+        test.setup_method(method)
 
     tmw_log = logging.getLogger('timermiddleware')
     tmw_log.disabled = 0  # gets disabled when .ini file is loaded; dumb.