From 2287368c0784cf62365b9834d370b258f2cfbc49 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Jun 04 2018 12:06:30 +0000
Subject: [PATCH 1/3] Use unittest2 for rhel6 compatibility


Fixes: https://pagure.io/koji/issue/830

---

diff --git a/koji/tasks.py b/koji/tasks.py
index 9135e6f..32ece24 100644
--- a/koji/tasks.py
+++ b/koji/tasks.py
@@ -131,7 +131,7 @@ def parse_task_params(method, params):
             break
         except koji.ParameterError as e:
             if not err:
-                err = e.message
+                err = e.args[0]
     else:
         raise koji.ParameterError("Invalid signature for %s: %s" % (method, err))
 
diff --git a/plugins/builder/runroot.py b/plugins/builder/runroot.py
index e956d78..cc7bdbb 100644
--- a/plugins/builder/runroot.py
+++ b/plugins/builder/runroot.py
@@ -251,39 +251,38 @@ class RunRootTask(koji.tasks.BaseTaskHandler):
         self.logger.info('New runroot')
         self.logger.info("Runroot mounts: %s" % mounts)
         fn = '%s/tmp/runroot_mounts' % rootdir
-        fslog = open(fn, 'a')
-        logfile = "%s/do_mounts.log" % self.workdir
-        uploadpath = self.getUploadDir()
-        error = None
-        for dev, path, type, opts in mounts:
-            if not path.startswith('/'):
-                raise koji.GenericError("invalid mount point: %s" % path)
-            mpoint = "%s%s" % (rootdir, path)
-            if opts is None:
-                opts = []
-            else:
-                opts = opts.split(',')
-            if 'bind' in opts:
-                #make sure dir exists
-                if not os.path.isdir(dev):
-                    error = koji.GenericError("No such directory or mount: %s" % dev)
+        with open(fn, 'a') as fslog:
+            logfile = "%s/do_mounts.log" % self.workdir
+            uploadpath = self.getUploadDir()
+            error = None
+            for dev, path, type, opts in mounts:
+                if not path.startswith('/'):
+                    raise koji.GenericError("invalid mount point: %s" % path)
+                mpoint = "%s%s" % (rootdir, path)
+                if opts is None:
+                    opts = []
+                else:
+                    opts = opts.split(',')
+                if 'bind' in opts:
+                    #make sure dir exists
+                    if not os.path.isdir(dev):
+                        error = koji.GenericError("No such directory or mount: %s" % dev)
+                        break
+                    type = 'none'
+                if 'bg' in opts:
+                    error = koji.GenericError("bad config: background mount not allowed")
                     break
-                type = 'none'
-            if 'bg' in opts:
-                error = koji.GenericError("bad config: background mount not allowed")
-                break
-            opts = ','.join(opts)
-            cmd = ['mount', '-t', type, '-o', opts, dev, mpoint]
-            self.logger.info("Mount command: %r" % cmd)
-            koji.ensuredir(mpoint)
-            status = log_output(self.session, cmd[0], cmd, logfile, uploadpath, logerror=True, append=True)
-            if not isSuccess(status):
-                error = koji.GenericError("Unable to mount %s: %s" \
-                        % (mpoint, parseStatus(status, cmd)))
-                break
-            fslog.write("%s\n" % mpoint)
-            fslog.flush()
-        fslog.close()
+                opts = ','.join(opts)
+                cmd = ['mount', '-t', type, '-o', opts, dev, mpoint]
+                self.logger.info("Mount command: %r" % cmd)
+                koji.ensuredir(mpoint)
+                status = log_output(self.session, cmd[0], cmd, logfile, uploadpath, logerror=True, append=True)
+                if not isSuccess(status):
+                    error = koji.GenericError("Unable to mount %s: %s" \
+                            % (mpoint, parseStatus(status, cmd)))
+                    break
+                fslog.write("%s\n" % mpoint)
+                fslog.flush()
         if error is not None:
             self.undo_mounts(rootdir, fatal=False)
             raise error
@@ -293,10 +292,9 @@ class RunRootTask(koji.tasks.BaseTaskHandler):
         mounts = set()
         fn = '%s/tmp/runroot_mounts' % rootdir
         if os.path.exists(fn):
-            fslog = open(fn, 'r')
-            for line in fslog.readlines():
-                mounts.add(line.strip())
-            fslog.close()
+            with open(fn, 'r') as fslog:
+                for line in fslog.readlines():
+                    mounts.add(line.strip())
         #also, check /proc/mounts just in case
         mounts |= set(scan_mounts(rootdir))
         mounts = sorted(mounts)
diff --git a/tests/test_builder/test_build_notification.py b/tests/test_builder/test_build_notification.py
index c6a30ea..6b3241f 100644
--- a/tests/test_builder/test_build_notification.py
+++ b/tests/test_builder/test_build_notification.py
@@ -4,8 +4,10 @@ import mock
 import os
 import smtplib
 import tempfile
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import koji.util
 from .loadkojid import kojid
diff --git a/tests/test_builder/test_choose_taskarch.py b/tests/test_builder/test_choose_taskarch.py
index c56c914..c198ab9 100644
--- a/tests/test_builder/test_choose_taskarch.py
+++ b/tests/test_builder/test_choose_taskarch.py
@@ -3,8 +3,11 @@ import unittest
 import mock
 import rpm
 import tempfile
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
-
 from .loadkojid import kojid
 from six.moves import range
 
diff --git a/tests/test_builder/test_taskparams.py b/tests/test_builder/test_taskparams.py
index 15fed47..69e9152 100644
--- a/tests/test_builder/test_taskparams.py
+++ b/tests/test_builder/test_taskparams.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import
 import inspect
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import koji.tasks
 
diff --git a/tests/test_cli/data/image-build-config.conf b/tests/test_cli/data/image-build-config.conf
new file mode 100644
index 0000000..aa29874
--- /dev/null
+++ b/tests/test_cli/data/image-build-config.conf
@@ -0,0 +1,30 @@
+[image-build]
+name = fedora-server-docker
+version = 26
+target = f26-candidate
+install_tree = https://alt.fedoraproject.org/pub/alt/releases/26/Cloud/$arch/os/
+arches = x86_64,ppc,arm64
+can_fail=ppc,arm64
+
+format = qcow2,rhevm-ova,vsphere-ova
+distro = Fedora-26
+repo = https://alt.fedoraproject.org/pub/alt/releases/26/Cloud/$arch/os/
+disk_size = 20
+
+ksversion = DEVEL
+kickstart = fedora-26-server-docker.ks
+ksurl = git://git.fedorahosted.org/git/spin-kickstarts.git?fedora26#68c40eb7
+specfile = git://git.fedorahosted.org/git/spin-kickstarts.git?spec_templates/fedora26#68c40eb7
+
+[ova-options]
+vsphere_product_version=26
+rhevm_description=Fedora Cloud 26
+vsphere_product_vendor_name=Fedora Project
+ovf_memory_mb=6144
+rhevm_default_display_type=1
+vsphere_product_name=Fedora Cloud 26
+ovf_cpu_count=4
+rhevm_os_descriptor=Fedora-26
+
+[factory-parameters]
+factory_test_ver=1.0
diff --git a/tests/test_cli/test_activate_session.py b/tests/test_cli/test_activate_session.py
index 987f08d..a97e6f8 100644
--- a/tests/test_cli/test_activate_session.py
+++ b/tests/test_cli/test_activate_session.py
@@ -1,7 +1,10 @@
 import mock
 import shutil
 import tempfile
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.lib import activate_session
 
diff --git a/tests/test_cli/test_add_group.py b/tests/test_cli/test_add_group.py
index a04c8c3..d9abda3 100644
--- a/tests/test_cli/test_add_group.py
+++ b/tests/test_cli/test_add_group.py
@@ -1,12 +1,13 @@
 from __future__ import absolute_import
 
-
 import mock
 import os
 import six
 import sys
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_add_group
 
@@ -108,7 +109,10 @@ class TestAddGroup(unittest.TestCase):
         session.getTag.assert_not_called()
         session.getTagGroups.assert_not_called()
         session.groupListAdd.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_add_group_pkg.py b/tests/test_cli/test_add_group_pkg.py
index 30f9307..4eddb13 100644
--- a/tests/test_cli/test_add_group_pkg.py
+++ b/tests/test_cli/test_add_group_pkg.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_add_group_pkg
 from . import utils
 
diff --git a/tests/test_cli/test_add_group_req.py b/tests/test_cli/test_add_group_req.py
index e713bb2..d8dd90d 100644
--- a/tests/test_cli/test_add_group_req.py
+++ b/tests/test_cli/test_add_group_req.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_add_group_req
 from . import utils
 
diff --git a/tests/test_cli/test_add_host.py b/tests/test_cli/test_add_host.py
index 331fb3f..11b83f0 100644
--- a/tests/test_cli/test_add_host.py
+++ b/tests/test_cli/test_add_host.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_add_host
 
@@ -125,7 +128,10 @@ class TestAddHost(unittest.TestCase):
         activate_session_mock.assert_not_called()
         session.hasHost.assert_not_called()
         session.addHost.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_add_host_to_channel.py b/tests/test_cli/test_add_host_to_channel.py
index 67ba327..80ebf18 100644
--- a/tests/test_cli/test_add_host_to_channel.py
+++ b/tests/test_cli/test_add_host_to_channel.py
@@ -4,7 +4,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_add_host_to_channel
 
@@ -193,7 +196,10 @@ class TestAddHostToChannel(unittest.TestCase):
         session.getChannel.assert_not_called()
         session.listChannels.assert_not_called()
         session.addHostToChannel.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_add_notification.py b/tests/test_cli/test_add_notification.py
index 51da4a2..7e121d4 100644
--- a/tests/test_cli/test_add_notification.py
+++ b/tests/test_cli/test_add_notification.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import koji
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 from six.moves import StringIO
 
 from koji_cli.commands import handle_add_notification
diff --git a/tests/test_cli/test_add_pkg.py b/tests/test_cli/test_add_pkg.py
index 8c807a6..8072a18 100644
--- a/tests/test_cli/test_add_pkg.py
+++ b/tests/test_cli/test_add_pkg.py
@@ -4,7 +4,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 
@@ -172,7 +175,10 @@ class TestAddPkg(unittest.TestCase):
         self.assertEqual(session.mock_calls,
                          [call.getUser(owner),
                           call.getTag(tag)])
-        self.assertEqual(cm.exception.code, 1)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 1)
+        else:
+            self.assertEqual(cm.exception.code, 1)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -210,7 +216,10 @@ class TestAddPkg(unittest.TestCase):
         session.getTag.assert_not_called()
         session.listPackages.assert_not_called()
         session.packageListAdd.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -244,7 +253,10 @@ class TestAddPkg(unittest.TestCase):
         session.getTag.assert_not_called()
         session.listPackages.assert_not_called()
         session.packageListAdd.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_add_tag.py b/tests/test_cli/test_add_tag.py
index e28f2d2..422b924 100644
--- a/tests/test_cli/test_add_tag.py
+++ b/tests/test_cli/test_add_tag.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_add_tag
 from . import utils
 
diff --git a/tests/test_cli/test_add_user.py b/tests/test_cli/test_add_user.py
index 6ec1b02..2b2f591 100644
--- a/tests/test_cli/test_add_user.py
+++ b/tests/test_cli/test_add_user.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_add_user
 from . import utils
 
diff --git a/tests/test_cli/test_add_volume.py b/tests/test_cli/test_add_volume.py
index f7021af..08c81ce 100644
--- a/tests/test_cli/test_add_volume.py
+++ b/tests/test_cli/test_add_volume.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_add_volume
 from . import utils
 
diff --git a/tests/test_cli/test_assign_task.py b/tests/test_cli/test_assign_task.py
index 4a039c3..90fce7e 100644
--- a/tests/test_cli/test_assign_task.py
+++ b/tests/test_cli/test_assign_task.py
@@ -3,9 +3,12 @@ import mock
 import os
 import six
 import sys
-import unittest
-import koji
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
+import koji
 from koji_cli.commands import handle_assign_task
 
 
@@ -102,7 +105,10 @@ class TestAssignTask(unittest.TestCase):
         activate_session_mock.assert_not_called()
         session.hasHost.assert_not_called()
         session.addHost.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_block_group_pkg.py b/tests/test_cli/test_block_group_pkg.py
index 47a641f..e035ca6 100644
--- a/tests/test_cli/test_block_group_pkg.py
+++ b/tests/test_cli/test_block_group_pkg.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_block_group_pkg
 from . import utils
 
diff --git a/tests/test_cli/test_block_group_req.py b/tests/test_cli/test_block_group_req.py
index e1a96dc..39d4253 100644
--- a/tests/test_cli/test_block_group_req.py
+++ b/tests/test_cli/test_block_group_req.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_block_group_req
 from . import utils
 
diff --git a/tests/test_cli/test_block_pkg.py b/tests/test_cli/test_block_pkg.py
index 914cda3..1bd09f9 100644
--- a/tests/test_cli/test_block_pkg.py
+++ b/tests/test_cli/test_block_pkg.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 
@@ -178,7 +181,10 @@ class TestBlockPkg(unittest.TestCase):
         session.getTag.assert_not_called()
         session.listPackages.assert_not_called()
         session.packageListBlock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_build.py b/tests/test_cli/test_build.py
index af97031..e4a601c 100644
--- a/tests/test_cli/test_build.py
+++ b/tests/test_cli/test_build.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_build, _progress_callback
 
@@ -162,7 +165,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -218,7 +224,10 @@ Options:
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 0)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 0)
+        else:
+            self.assertEqual(cm.exception.code, 0)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -264,7 +273,10 @@ Options:
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -354,7 +366,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -402,7 +417,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -450,7 +468,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.build.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_call.py b/tests/test_cli/test_call.py
index 0fb4907..c45901d 100644
--- a/tests/test_cli/test_call.py
+++ b/tests/test_cli/test_call.py
@@ -1,8 +1,11 @@
 from __future__ import absolute_import
+import json
 import mock
 import six
-import unittest
-import json
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_call
 from . import utils
@@ -118,13 +121,16 @@ class TestCall(utils.CliTestCase):
         }
 
         for mod, msg in module.items():
-            with mock.patch('koji_cli.commands.%s' % mod, new=None), \
-                 self.assertRaises(SystemExit) as cm:
-                handle_call(options, session, arguments)
+            with mock.patch('koji_cli.commands.%s' % mod, new=None):
+                with self.assertRaises(SystemExit) as cm:
+                    handle_call(options, session, arguments)
             expected = self.format_error_message(msg)
             self.assert_console_message(stderr, expected)
             activate_session_mock.assert_not_called()
-            self.assertEqual(cm.exception.code, 2)
+            if isinstance(cm.exception, int):
+                self.assertEqual(cm.exception, 2)
+            else:
+                self.assertEqual(cm.exception.code, 2)
 
     def test_handle_call_help(self):
         """Test handle_call help message"""
diff --git a/tests/test_cli/test_chain_build.py b/tests/test_cli/test_chain_build.py
index dd616ad..da7a62a 100644
--- a/tests/test_cli/test_chain_build.py
+++ b/tests/test_cli/test_chain_build.py
@@ -4,7 +4,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_chain_build
 
@@ -119,7 +122,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.chainBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -163,7 +169,10 @@ Options:
         self.session.chainBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 0)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 0)
+        else:
+            self.assertEqual(cm.exception.code, 0)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -212,7 +221,10 @@ Options:
         self.session.chainBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -271,7 +283,10 @@ Options:
         self.session.chainBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -453,7 +468,10 @@ Target target is not usable for a chain-build
 If there are no dependencies, use the build command instead
 """ % (progname, progname)
             self.assertMultiLineEqual(actual, expected)
-            self.assertEqual(cm.exception.code, 2)
+            if isinstance(cm.exception, int):
+                self.assertEqual(cm.exception, 2)
+            else:
+                self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_disable_host.py b/tests/test_cli/test_disable_host.py
index a249ab4..5b39e6f 100644
--- a/tests/test_cli/test_disable_host.py
+++ b/tests/test_cli/test_disable_host.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 from koji_cli.commands import handle_disable_host
diff --git a/tests/test_cli/test_disable_user.py b/tests/test_cli/test_disable_user.py
index ebcd03d..e8598a4 100644
--- a/tests/test_cli/test_disable_user.py
+++ b/tests/test_cli/test_disable_user.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_disable_user
 from . import utils
 
diff --git a/tests/test_cli/test_dist_repo.py b/tests/test_cli/test_dist_repo.py
index 527cd81..0f3fcd3 100644
--- a/tests/test_cli/test_dist_repo.py
+++ b/tests/test_cli/test_dist_repo.py
@@ -1,9 +1,13 @@
 from __future__ import absolute_import
 from __future__ import print_function
+import copy
 import mock
 import six
-import unittest
-import copy
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 
 from koji_cli.commands import handle_dist_repo
 from . import utils
diff --git a/tests/test_cli/test_download_file.py b/tests/test_cli/test_download_file.py
index 158e730..4abdf71 100644
--- a/tests/test_cli/test_download_file.py
+++ b/tests/test_cli/test_download_file.py
@@ -3,7 +3,10 @@ import mock
 import six
 import shutil
 import tempfile
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.lib import download_file, _download_progress
 
@@ -45,7 +48,11 @@ class TestDownloadFile(unittest.TestCase):
         actual = self.stdout.getvalue()
         expected = 'Downloading: %s\n' % self.tempdir
         self.assertMultiLineEqual(actual, expected)
-        self.assertEqual(cm.exception.args, (21, 'Is a directory'))
+        if isinstance(cm.exception, tuple):
+            self.assertEqual(cm.exception[0], 21)
+            self.assertEqual(cm.exception[1], 'Is a directory')
+        else:
+            self.assertEqual(cm.exception.args, (21, 'Is a directory'))
         self.requests_get.assert_called_once()
 
     @mock_open()
diff --git a/tests/test_cli/test_download_logs.py b/tests/test_cli/test_download_logs.py
index 976eefd..982ad15 100644
--- a/tests/test_cli/test_download_logs.py
+++ b/tests/test_cli/test_download_logs.py
@@ -88,7 +88,11 @@ class TestDownloadLogs(utils.CliTestCase):
         out_file = six.StringIO()
         self.custom_open['kojilogs/x86_64-123456/volume1/file1.log'] = out_file
 
-        with mock.patch('koji_cli.commands.open', new=self.mock_builtin_open):
+        if six.PY2:
+            target = '__builtin__.open'
+        else:
+            target = 'builtins.open'
+        with mock.patch(target, new=self.mock_builtin_open):
             anon_handle_download_logs(self.options, self.session, [str(task_id)])
 
         self.session.getTaskInfo.assert_called_once_with(task_id)
diff --git a/tests/test_cli/test_download_task.py b/tests/test_cli/test_download_task.py
index d698a4e..2635b25 100644
--- a/tests/test_cli/test_download_task.py
+++ b/tests/test_cli/test_download_task.py
@@ -4,7 +4,10 @@ from mock import call
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_download_task
 
@@ -204,7 +207,10 @@ class TestDownloadTask(unittest.TestCase):
         self.session.getTaskChildren.assert_not_called()
         self.list_task_output_all_volumes.assert_called_once_with(self.session, task_id)
         self.download_file.assert_not_called()
-        self.assertEqual(cm.exception.code, 1)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 1)
+        else:
+            self.assertEqual(cm.exception.code, 1)
 
     def test_handle_download_parent_not_finished(self):
         task_id = 123333
@@ -237,7 +243,10 @@ class TestDownloadTask(unittest.TestCase):
         self.session.getTaskChildren.assert_not_called()
         self.list_task_output_all_volumes.assert_called_once_with(self.session, task_id)
         self.download_file.assert_not_called()
-        self.assertEqual(cm.exception.code, 1)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 1)
+        else:
+            self.assertEqual(cm.exception.code, 1)
 
     def test_handle_download_child_not_finished(self):
         task_id = 123333
@@ -268,7 +277,10 @@ class TestDownloadTask(unittest.TestCase):
         self.session.getTaskChildren.assert_called_once_with(task_id)
         self.list_task_output_all_volumes.assert_called_once_with(self.session, 22222)
         self.download_file.assert_not_called()
-        self.assertEqual(cm.exception.code, 1)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 1)
+        else:
+            self.assertEqual(cm.exception.code, 1)
 
     def test_handle_download_invalid_file_name(self):
         task_id = 123333
@@ -295,7 +307,10 @@ class TestDownloadTask(unittest.TestCase):
         self.session.getTaskChildren.assert_not_called()
         self.list_task_output_all_volumes.assert_called_once_with(self.session, task_id)
         self.download_file.assert_not_called()
-        self.assertEqual(cm.exception.code, 1)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 1)
+        else:
+            self.assertEqual(cm.exception.code, 1)
 
     def test_handle_download_help(self):
         args = ['--help']
@@ -321,7 +336,10 @@ Options:
         actual = self.stderr.getvalue()
         expected = ''
         self.assertEqual(actual, expected)
-        self.assertEqual(cm.exception.code, 0)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 0)
+        else:
+            self.assertEqual(cm.exception.code, 0)
 
     def test_handle_download_no_task_id(self):
         args = []
@@ -340,7 +358,10 @@ Options:
 %s: error: Please specify a task ID
 """ % (progname, progname)
         self.assertEqual(actual, expected)
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     def test_handle_download_multi_task_id(self):
         args = ["123", "456"]
@@ -359,7 +380,10 @@ Options:
 %s: error: Only one task ID may be specified
 """ % (progname, progname)
         self.assertEqual(actual, expected)
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_edit_host.py b/tests/test_cli/test_edit_host.py
index e6aca06..4b255d4 100644
--- a/tests/test_cli/test_edit_host.py
+++ b/tests/test_cli/test_edit_host.py
@@ -3,7 +3,11 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from mock import call
 
 from koji_cli.commands import handle_edit_host
@@ -171,7 +175,10 @@ class TestEditHost(unittest.TestCase):
         session.getHost.assert_not_called()
         session.editHost.assert_not_called()
         session.multiCall.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_edit_notification.py b/tests/test_cli/test_edit_notification.py
index 8204709..b265df1 100644
--- a/tests/test_cli/test_edit_notification.py
+++ b/tests/test_cli/test_edit_notification.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import koji
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 from six.moves import StringIO
 
 from koji_cli.commands import handle_edit_notification
diff --git a/tests/test_cli/test_edit_tag.py b/tests/test_cli/test_edit_tag.py
index a2f79ba..5244a63 100644
--- a/tests/test_cli/test_edit_tag.py
+++ b/tests/test_cli/test_edit_tag.py
@@ -3,8 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_edit_tag
 
@@ -137,7 +139,10 @@ Options:
         # Finally, assert that things were called as we expected.
         activate_session_mock.assert_not_called()
         session.editTag2.assert_not_called()
-        self.assertEqual(cm.exception.code, 0)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 0)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -167,7 +172,10 @@ Options:
         # Finally, assert that things were called as we expected.
         activate_session_mock.assert_not_called()
         session.editTag2.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_enable_host.py b/tests/test_cli/test_enable_host.py
index d0fc263..f153584 100644
--- a/tests/test_cli/test_enable_host.py
+++ b/tests/test_cli/test_enable_host.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 from koji_cli.commands import handle_enable_host
diff --git a/tests/test_cli/test_enable_user.py b/tests/test_cli/test_enable_user.py
index e61eb3a..2861ce1 100644
--- a/tests/test_cli/test_enable_user.py
+++ b/tests/test_cli/test_enable_user.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_enable_user
 from . import utils
 
diff --git a/tests/test_cli/test_grant_cg_access.py b/tests/test_cli/test_grant_cg_access.py
index 2b63d89..f445eea 100644
--- a/tests/test_cli/test_grant_cg_access.py
+++ b/tests/test_cli/test_grant_cg_access.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_grant_cg_access
 from . import utils
diff --git a/tests/test_cli/test_grant_permission.py b/tests/test_cli/test_grant_permission.py
index ecd38ce..f224de2 100644
--- a/tests/test_cli/test_grant_permission.py
+++ b/tests/test_cli/test_grant_permission.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_grant_permission
 from . import utils
diff --git a/tests/test_cli/test_hello.py b/tests/test_cli/test_hello.py
index 4f19d1f..f9cbf19 100644
--- a/tests/test_cli/test_hello.py
+++ b/tests/test_cli/test_hello.py
@@ -2,9 +2,12 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
-import koji
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
+import koji
 from koji_cli.commands import handle_moshimoshi, _printable_unicode
 from . import utils
 
diff --git a/tests/test_cli/test_image_build.py b/tests/test_cli/test_image_build.py
index e1e0f10..38a69b5 100644
--- a/tests/test_cli/test_image_build.py
+++ b/tests/test_cli/test_image_build.py
@@ -2,16 +2,20 @@ from __future__ import absolute_import
 import mock
 import six
 import os
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import koji
 
 from koji_cli.commands import handle_image_build, _build_image_oz
 from . import utils
 
+ConfigParser = six.moves.configparser.ConfigParser
 
 TASK_OPTIONS = {
     "background": None,
-    "config": "build-image-config.conf",
     "disk_size": "20",
     "distro": "Fedora-26",
     "factory_parameter": [
@@ -53,6 +57,13 @@ TASK_OPTIONS = {
     "wait": None,
 }
 
+def mock_open():
+    """Return the right patch decorator for open"""
+    if six.PY2:
+        return mock.patch('__builtin__.open')
+    else:
+        return mock.patch('builtins.open')
+
 
 class Options(object):
     def __init__(self, init_dict):
@@ -208,30 +219,10 @@ class TestImageBuild(utils.CliTestCase):
     # Show long diffs in error output...
     maxDiff = None
 
-    def mock_os_path_exists(self, filepath):
-        if filepath in self.custom_os_path_exists:
-            return self.custom_os_path_exists[filepath]
-        return self.os_path_exists(filepath)
-
-    def mock_builtin_open(self, filepath, *args):
-        if filepath in self.custom_open:
-            return self.custom_open[filepath]
-        return self.builtin_open(filepath, *args)
-
     def setUp(self):
-        self.os_path_exists = os.path.exists
-        self.custom_os_path_exists = {}
-
-        self.builtin_open = None
-        if six.PY2:
-            self.builtin_open = __builtins__['open']
-        else:
-            import builtins
-            self.builtin_open = builtins.open
-        self.custom_open = {}
-
         self.options = mock.MagicMock()
         self.session = mock.MagicMock()
+        self.configparser = mock.patch('six.moves.configparser.ConfigParser').start()
 
         self.error_format = """Usage: %s image-build [options] <name> <version> <target> <install-tree-url> <arch> [<arch>...]
        %s image-build --config FILE
@@ -241,80 +232,43 @@ class TestImageBuild(utils.CliTestCase):
 %s: error: {message}
 """ % (self.progname, self.progname, self.progname)
 
+    def tearDown(self):
+        mock.patch.stopall()
+
     @mock.patch('koji_cli.commands._build_image_oz')
     def test_handle_image_build_with_config(self, build_image_oz_mock):
         """Test handle_image_build argument with --config cases"""
 
         # Case 1, config file not exist case
-        config_file = "build-image-config.conf"
-        expected = "%s not found!" % config_file
-
         self.assert_system_exit(
                 handle_image_build,
                 self.options,
                 self.session,
-                ['--config', config_file],
-                stderr=self.format_error_message(expected),
+                ['--config', '/nonexistent-file-755684354'],
+                stderr=self.format_error_message('/nonexistent-file-755684354 not found!'),
                 activate_session=None)
 
         # Case 2, no image-build section in config file
-        self.custom_os_path_exists[config_file] = True
-        self.custom_open[config_file] = six.StringIO('')
 
         expected = "single section called [%s] is required" % "image-build"
 
-        with mock.patch('os.path.exists', new=self.mock_os_path_exists), \
-                mock.patch('koji_cli.commands.open', new=self.mock_builtin_open):
-            self.assert_system_exit(
-                handle_image_build,
-                self.options,
-                self.session,
-                ['--config', config_file],
-                stderr=self.format_error_message(expected),
-                activate_session=None)
-
-        fake_config = """
-[image-build]
-name = fedora-server-docker
-version = 26
-target = f26-candidate
-install_tree = https://alt.fedoraproject.org/pub/alt/releases/26/Cloud/$arch/os/
-arches = x86_64,ppc,arm64
-can_fail=ppc,arm64
-
-format = qcow2,rhevm-ova,vsphere-ova
-distro = Fedora-26
-repo = https://alt.fedoraproject.org/pub/alt/releases/26/Cloud/$arch/os/
-disk_size = 20
-
-ksversion = DEVEL
-kickstart = fedora-26-server-docker.ks
-ksurl = git://git.fedorahosted.org/git/spin-kickstarts.git?fedora26#68c40eb7
-specfile = git://git.fedorahosted.org/git/spin-kickstarts.git?spec_templates/fedora26#68c40eb7
-
-[ova-options]
-vsphere_product_version=26
-rhevm_description=Fedora Cloud 26
-vsphere_product_vendor_name=Fedora Project
-ovf_memory_mb=6144
-rhevm_default_display_type=1
-vsphere_product_name=Fedora Cloud 26
-ovf_cpu_count=4
-rhevm_os_descriptor=Fedora-26
-
-[factory-parameters]
-factory_test_ver=1.0
-"""
-        self.custom_open[config_file] = six.StringIO(fake_config)
-
-        with mock.patch('os.path.exists', new=self.mock_os_path_exists), \
-                mock.patch('koji_cli.commands.open', new=self.mock_builtin_open):
-            handle_image_build(
-                self.options,
-                self.session,
-                ['--config', config_file])
+        self.configparser.return_value = ConfigParser()
+        self.assert_system_exit(
+            handle_image_build,
+            self.options,
+            self.session,
+            ['--config', '/dev/null'],
+            stderr=self.format_error_message(expected),
+            activate_session=None)
+
+        config_file = os.path.join(os.path.dirname(__file__), 'data/image-build-config.conf')
+        handle_image_build(
+            self.options,
+            self.session,
+            ['--config', config_file])
 
         args, kwargs = build_image_oz_mock.call_args
+        TASK_OPTIONS['config'] = config_file
         self.assertDictEqual(TASK_OPTIONS, args[1].__dict__)
 
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_image_build_indirection.py b/tests/test_cli/test_image_build_indirection.py
index a9f9bb2..eb4c853 100644
--- a/tests/test_cli/test_image_build_indirection.py
+++ b/tests/test_cli/test_image_build_indirection.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import koji
 
 from koji_cli.commands import handle_image_build_indirection, _build_image_indirection
@@ -145,10 +149,10 @@ class TestBuildImageIndirection(utils.CliTestCase):
             setattr(self.task_opts, r, None)
             expected = "Missing the following required options: "
             expected += "--" + r.replace('_', '-') + "\n"
-            with self.assertRaises(koji.GenericError) as cm, \
-                    mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
-                _build_image_indirection(
-                    self.options, self.task_opts, self.session, [])
+            with self.assertRaises(koji.GenericError) as cm:
+                with  mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+                    _build_image_indirection(
+                        self.options, self.task_opts, self.session, [])
             self.assert_console_message(stdout, expected)
             self.assertEqual(
                 str(cm.exception), "Missing required options specified above")
diff --git a/tests/test_cli/test_import.py b/tests/test_cli/test_import.py
index e229ba2..24bce3a 100644
--- a/tests/test_cli/test_import.py
+++ b/tests/test_cli/test_import.py
@@ -1,13 +1,21 @@
 from __future__ import absolute_import
 import mock
-import six
-import unittest
-import koji
 import os
+import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
+import koji
 from koji_cli.commands import handle_import
 from . import utils
 
+def md5_to_bytes(s):
+    if six.PY2:
+        return bytearray.fromhex(unicode(s))
+    else:
+        return bytearray.fromhex(s)
 
 class TestImport(utils.CliTestCase):
 
@@ -46,7 +54,7 @@ class TestImport(utils.CliTestCase):
         self.srpm_header = {
             'sourcepackage': 1,
             'name': 'bash',
-            'sigmd5': bytearray.fromhex(self.md5),
+            'sigmd5': md5_to_bytes(self.md5),
             'epoch': None,
             'version': '4.4.12',
             'release': '5.fc26',
@@ -57,7 +65,7 @@ class TestImport(utils.CliTestCase):
         self.rpm_header = {
             'sourcepackage': None,
             'name': 'bash',
-            'sigmd5': bytearray.fromhex(self.md5),
+            'sigmd5': md5_to_bytes(self.md5),
             'epoch': None,
             'version': '4.4.12',
             'release': '5.fc26',
@@ -86,14 +94,14 @@ class TestImport(utils.CliTestCase):
         fake_srv_path = kwargs.get('srv_path', '/path/to/server/import')
         upload_rpm_mock = kwargs.get('upload_rpm_mock', session.uploadWrapper)
 
-        with mock.patch('koji.get_header_fields') as get_header_fields_mock, \
-                mock.patch('koji_cli.commands._unique_path') as unique_path_mock, \
-                mock.patch('koji_cli.commands.activate_session') as activate_session_mock, \
-                mock.patch('sys.stdout', new_callable=six.StringIO) as stdout, \
-                upload_rpm_mock:
-            get_header_fields_mock.return_value = rpm_header
-            unique_path_mock.return_value = fake_srv_path
-            handle_import(options, session, arguments)
+        with mock.patch('koji.get_header_fields') as get_header_fields_mock:
+            with mock.patch('koji_cli.commands._unique_path') as unique_path_mock:
+                with mock.patch('koji_cli.commands.activate_session') as activate_session_mock:
+                    with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+                        with upload_rpm_mock:
+                            get_header_fields_mock.return_value = rpm_header
+                            unique_path_mock.return_value = fake_srv_path
+                            handle_import(options, session, arguments)
 
         # check output message
         self.assert_console_message(stdout, expected)
@@ -128,11 +136,11 @@ class TestImport(utils.CliTestCase):
         expected = kwargs.get('expected', None)
         rpm_header = kwargs.get('rpm_header', {})
 
-        with mock.patch('koji.get_header_fields') as get_header_fields_mock, \
-                mock.patch('koji_cli.commands.activate_session') as activate_session_mock, \
-                mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
-            get_header_fields_mock.return_value = rpm_header
-            handle_import(options, session, arguments)
+        with mock.patch('koji.get_header_fields') as get_header_fields_mock:
+            with mock.patch('koji_cli.commands.activate_session') as activate_session_mock:
+                with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+                    get_header_fields_mock.return_value = rpm_header
+                    handle_import(options, session, arguments)
 
         # check output message
         self.assert_console_message(stdout, expected)
@@ -300,11 +308,11 @@ class TestImport(utils.CliTestCase):
             'payloadhash': self.md5
         }
         expected = "Build %s state is %s. Skipping import\n" % (nvr, 'FAILED')
-        with mock.patch('koji.get_header_fields') as get_header_fields_mock, \
-                mock.patch('koji_cli.commands.activate_session') as activate_session_mock, \
-                mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
-            get_header_fields_mock.return_value = self.srpm_header
-            handle_import(options, session, arguments)
+        with mock.patch('koji.get_header_fields') as get_header_fields_mock:
+            with mock.patch('koji_cli.commands.activate_session') as activate_session_mock:
+                with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+                    get_header_fields_mock.return_value = self.srpm_header
+                    handle_import(options, session, arguments)
         activate_session_mock.assert_called_with(session, options)
         self.assert_console_message(stdout, expected)
 
diff --git a/tests/test_cli/test_import_cg.py b/tests/test_cli/test_import_cg.py
index 0e140cd..328e531 100644
--- a/tests/test_cli/test_import_cg.py
+++ b/tests/test_cli/test_import_cg.py
@@ -174,32 +174,32 @@ class TestImportCG(utils.CliTestCase):
         # is matched return the value we expected.
         self.custom_os_path_exists['/real/path/filename'] = False
 
-        with mock.patch(utils.get_builtin_open()), \
-                mock.patch('os.path.exists', new=self.mock_os_path_exists), \
-                mock.patch('koji_cli.commands.json') as json_mock:
-
-            # Case 3. metafile doesn't have output section
-            json_mock.load.return_value = {}
-            expected = "Metadata contains no output\n"
-            self.assert_system_exit(
-                handle_import_cg,
-                options,
-                session,
-                arguments,
-                stdout=expected,
-                exit_code=1)
-
-            # Case 4. path not exist
-            file_path = '%(relpath)s/%(filename)s' % metadata['output'][1]
-            json_mock.load.return_value = metadata
-            expected = self.format_error_message(
-                "No such file: %s" % file_path)
-            self.assert_system_exit(
-                handle_import_cg,
-                options,
-                session,
-                arguments,
-                stderr=expected)
+        with mock.patch(utils.get_builtin_open()):
+            with mock.patch('os.path.exists', new=self.mock_os_path_exists):
+                with mock.patch('koji_cli.commands.json') as json_mock:
+
+                    # Case 3. metafile doesn't have output section
+                    json_mock.load.return_value = {}
+                    expected = "Metadata contains no output\n"
+                    self.assert_system_exit(
+                        handle_import_cg,
+                        options,
+                        session,
+                        arguments,
+                        stdout=expected,
+                        exit_code=1)
+
+                    # Case 4. path not exist
+                    file_path = '%(relpath)s/%(filename)s' % metadata['output'][1]
+                    json_mock.load.return_value = metadata
+                    expected = self.format_error_message(
+                        "No such file: %s" % file_path)
+                    self.assert_system_exit(
+                        handle_import_cg,
+                        options,
+                        session,
+                        arguments,
+                        stderr=expected)
 
     def test_handle_import_cg_help(self):
         """Test handle_import_cg help message"""
diff --git a/tests/test_cli/test_import_comps.py b/tests/test_cli/test_import_comps.py
index 5cf9224..07a809c 100644
--- a/tests/test_cli/test_import_comps.py
+++ b/tests/test_cli/test_import_comps.py
@@ -4,7 +4,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 try:
     import libcomps
@@ -213,7 +216,10 @@ class TestImportComps(unittest.TestCase):
         session.getTag.assert_not_called()
         session.getTagGroups.assert_not_called()
         session.groupListAdd.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @unittest.skipIf(libcomps is None, "No libcomps")
     @mock.patch('sys.stdout', new_callable=six.StringIO)
diff --git a/tests/test_cli/test_import_sig.py b/tests/test_cli/test_import_sig.py
index f5d682e..332a708 100644
--- a/tests/test_cli/test_import_sig.py
+++ b/tests/test_cli/test_import_sig.py
@@ -1,11 +1,14 @@
 from __future__ import absolute_import
+import base64
+import copy
+import hashlib
 import mock
-import six
-import unittest
 import random
-import hashlib
-import copy
-import base64
+import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 from koji_cli.commands import handle_import_sig
diff --git a/tests/test_cli/test_list_api.py b/tests/test_cli/test_list_api.py
index 77ef6e3..1d923c4 100644
--- a/tests/test_cli/test_list_api.py
+++ b/tests/test_cli/test_list_api.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_list_api
 from . import utils
diff --git a/tests/test_cli/test_list_channels.py b/tests/test_cli/test_list_channels.py
index 07f63e9..3b1191a 100644
--- a/tests/test_cli/test_list_channels.py
+++ b/tests/test_cli/test_list_channels.py
@@ -1,6 +1,9 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 from six.moves import StringIO
 
 import koji
diff --git a/tests/test_cli/test_list_commands.py b/tests/test_cli/test_list_commands.py
index 49a9140..bc982ce 100644
--- a/tests/test_cli/test_list_commands.py
+++ b/tests/test_cli/test_list_commands.py
@@ -2,7 +2,10 @@ from __future__ import absolute_import
 import mock
 import os
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from . import loadcli
 cli = loadcli.cli
diff --git a/tests/test_cli/test_list_groups.py b/tests/test_cli/test_list_groups.py
index 61e12d0..70c85f5 100644
--- a/tests/test_cli/test_list_groups.py
+++ b/tests/test_cli/test_list_groups.py
@@ -1,8 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
 import time
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_list_groups
 from . import utils
diff --git a/tests/test_cli/test_list_notifications.py b/tests/test_cli/test_list_notifications.py
index 89e1960..ca173b9 100644
--- a/tests/test_cli/test_list_notifications.py
+++ b/tests/test_cli/test_list_notifications.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 from six.moves import StringIO
 
 import koji
@@ -37,8 +40,8 @@ class TestListNotifications(unittest.TestCase):
         self.maxDiff=None
         self.assertMultiLineEqual(actual, expected)
         activate_session_mock.assert_called_once_with(self.session, self.options)
-        self.session.getTag.assert_has_calls((mock.call(1), mock.call(1)))
-        self.session.getPackage.assert_has_calls((mock.call(11), mock.call(11)))
+        self.session.getTag.assert_has_calls([mock.call(1), mock.call(1)])
+        self.session.getPackage.assert_has_calls([mock.call(11), mock.call(11)])
         self.session.getUser.assert_not_called()
         self.session.getBuildNotifications.assert_called_once_with(None)
 
@@ -67,8 +70,8 @@ class TestListNotifications(unittest.TestCase):
         self.maxDiff=None
         self.assertMultiLineEqual(actual, expected)
         activate_session_mock.assert_called_once_with(self.session, self.options)
-        self.session.getTag.assert_has_calls((mock.call(1), mock.call(1)))
-        self.session.getPackage.assert_has_calls((mock.call(11), mock.call(11)))
+        self.session.getTag.assert_has_calls([mock.call(1), mock.call(1)])
+        self.session.getPackage.assert_has_calls([mock.call(11), mock.call(11)])
         self.session.getUser.assert_called_once_with('random_name')
         self.session.getBuildNotifications.assert_called_once_with(321)
 
diff --git a/tests/test_cli/test_list_permissions.py b/tests/test_cli/test_list_permissions.py
index a131ded..b817d1f 100644
--- a/tests/test_cli/test_list_permissions.py
+++ b/tests/test_cli/test_list_permissions.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_list_permissions
 from . import utils
 
diff --git a/tests/test_cli/test_list_tasks.py b/tests/test_cli/test_list_tasks.py
index 9564477..497a799 100644
--- a/tests/test_cli/test_list_tasks.py
+++ b/tests/test_cli/test_list_tasks.py
@@ -1,6 +1,9 @@
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 from koji_cli.lib import _list_tasks
diff --git a/tests/test_cli/test_list_volumes.py b/tests/test_cli/test_list_volumes.py
index 714d5b8..0df5102 100644
--- a/tests/test_cli/test_list_volumes.py
+++ b/tests/test_cli/test_list_volumes.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_list_volumes
 from . import utils
 
diff --git a/tests/test_cli/test_load_plugins.py b/tests/test_cli/test_load_plugins.py
index 411ee96..4747d63 100644
--- a/tests/test_cli/test_load_plugins.py
+++ b/tests/test_cli/test_load_plugins.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import os
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from . import loadcli
 cli = loadcli.cli
diff --git a/tests/test_cli/test_maven_build.py b/tests/test_cli/test_maven_build.py
index 7b01eb8..a3d5bf9 100644
--- a/tests/test_cli/test_maven_build.py
+++ b/tests/test_cli/test_maven_build.py
@@ -5,7 +5,10 @@ import optparse
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_maven_build
 
@@ -122,7 +125,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -162,7 +168,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -230,7 +239,10 @@ Options:
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 0)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 0)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -271,7 +283,10 @@ Options:
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -316,7 +331,10 @@ Options:
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -361,7 +379,10 @@ Options:
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('sys.stdout', new_callable=six.StringIO)
@@ -467,7 +488,10 @@ Task info: weburl/taskinfo?taskID=1
             build_opts.inis, scratch=scratch, section=section)
         maven_opts_mock.assert_not_called()
         self.session.mavenBuild.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
         stdout.seek(0)
         stdout.truncate()
@@ -495,7 +519,10 @@ Task info: weburl/taskinfo?taskID=1
             build_opts.inis, scratch=scratch, section=section)
         maven_opts_mock.assert_not_called()
         self.session.mavenBuild.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stderr', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
@@ -547,7 +574,10 @@ Task info: weburl/taskinfo?taskID=1
         self.session.mavenBuild.assert_not_called()
         self.session.logout.assert_not_called()
         watch_tasks_mock.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.activate_session')
diff --git a/tests/test_cli/test_maven_chain.py b/tests/test_cli/test_maven_chain.py
index f9dbdcb..bb4380c 100644
--- a/tests/test_cli/test_maven_chain.py
+++ b/tests/test_cli/test_maven_chain.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_maven_chain
 from . import utils
diff --git a/tests/test_cli/test_mock_config.py b/tests/test_cli/test_mock_config.py
index 64b14ba..78fe928 100644
--- a/tests/test_cli/test_mock_config.py
+++ b/tests/test_cli/test_mock_config.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_mock_config
 from . import utils
diff --git a/tests/test_cli/test_move_build.py b/tests/test_cli/test_move_build.py
index 6842757..da184be 100644
--- a/tests/test_cli/test_move_build.py
+++ b/tests/test_cli/test_move_build.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_move_build
 from . import utils
 
diff --git a/tests/test_cli/test_regen_repo.py b/tests/test_cli/test_regen_repo.py
index 17f9b43..43eff0b 100644
--- a/tests/test_cli/test_regen_repo.py
+++ b/tests/test_cli/test_regen_repo.py
@@ -1,9 +1,12 @@
 from __future__ import absolute_import
 from __future__ import print_function
+import copy
 import mock
 import six
-import unittest
-import copy
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_regen_repo
 from . import utils
diff --git a/tests/test_cli/test_remove_channel.py b/tests/test_cli/test_remove_channel.py
index 9a16a2f..c1381ac 100644
--- a/tests/test_cli/test_remove_channel.py
+++ b/tests/test_cli/test_remove_channel.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_remove_channel
 
@@ -120,7 +123,10 @@ class TestRemoveChannel(unittest.TestCase):
         activate_session_mock.assert_not_called()
         session.getChannel.assert_not_called()
         session.removeChannel.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_remove_host_from_channel.py b/tests/test_cli/test_remove_host_from_channel.py
index b44b083..dc5ae0d 100644
--- a/tests/test_cli/test_remove_host_from_channel.py
+++ b/tests/test_cli/test_remove_host_from_channel.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_remove_host_from_channel
 
@@ -134,7 +137,10 @@ class TestRemoveHostFromChannel(unittest.TestCase):
         session.getHost.assert_not_called()
         session.listChannels.assert_not_called()
         session.removeHostFromChannel.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_remove_notification.py b/tests/test_cli/test_remove_notification.py
index 2d08730..df253a5 100644
--- a/tests/test_cli/test_remove_notification.py
+++ b/tests/test_cli/test_remove_notification.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import koji
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from six.moves import StringIO
 
 from koji_cli.commands import handle_remove_notification
diff --git a/tests/test_cli/test_remove_pkg.py b/tests/test_cli/test_remove_pkg.py
index f6b6d91..455f3c0 100644
--- a/tests/test_cli/test_remove_pkg.py
+++ b/tests/test_cli/test_remove_pkg.py
@@ -3,7 +3,11 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from mock import call
 
 
@@ -218,7 +222,10 @@ class TestRemovePkg(unittest.TestCase):
         session.getTag.assert_not_called()
         session.listPackages.assert_not_called()
         session.packageListRemove.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_rename_channel.py b/tests/test_cli/test_rename_channel.py
index 65a7c91..404a4ef 100644
--- a/tests/test_cli/test_rename_channel.py
+++ b/tests/test_cli/test_rename_channel.py
@@ -3,7 +3,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_rename_channel
 
@@ -96,7 +99,11 @@ class TestRenameChannel(unittest.TestCase):
         activate_session_mock.assert_not_called()
         session.getChannel.assert_not_called()
         session.renameChannel.assert_not_called()
-        self.assertEqual(cm.exception.code, 2)
+        if isinstance(cm.exception, int):
+            # python 2.6.6
+            self.assertEqual(cm.exception, 2)
+        else:
+            self.assertEqual(cm.exception.code, 2)
 
 
 if __name__ == '__main__':
diff --git a/tests/test_cli/test_restart_host.py b/tests/test_cli/test_restart_host.py
index 4383caf..a70c919 100644
--- a/tests/test_cli/test_restart_host.py
+++ b/tests/test_cli/test_restart_host.py
@@ -1,9 +1,12 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
-import koji
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
+import koji
 from koji_cli.commands import handle_restart_hosts
 from . import utils
 
diff --git a/tests/test_cli/test_resubmit.py b/tests/test_cli/test_resubmit.py
index 1b9e6f2..f062dd6 100644
--- a/tests/test_cli/test_resubmit.py
+++ b/tests/test_cli/test_resubmit.py
@@ -2,7 +2,10 @@ from __future__ import absolute_import
 from __future__ import print_function
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_resubmit
 from . import utils
diff --git a/tests/test_cli/test_revoke_cg_access.py b/tests/test_cli/test_revoke_cg_access.py
index 8b3107c..9aa381a 100644
--- a/tests/test_cli/test_revoke_cg_access.py
+++ b/tests/test_cli/test_revoke_cg_access.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_revoke_cg_access
 from . import utils
diff --git a/tests/test_cli/test_revoke_permission.py b/tests/test_cli/test_revoke_permission.py
index e532df0..f807145 100644
--- a/tests/test_cli/test_revoke_permission.py
+++ b/tests/test_cli/test_revoke_permission.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_revoke_permission
 from . import utils
diff --git a/tests/test_cli/test_running_in_bg.py b/tests/test_cli/test_running_in_bg.py
index 69497bd..0f5169d 100644
--- a/tests/test_cli/test_running_in_bg.py
+++ b/tests/test_cli/test_running_in_bg.py
@@ -1,7 +1,9 @@
 from __future__ import absolute_import
-import unittest
-
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.lib import _running_in_bg
 
diff --git a/tests/test_cli/test_search.py b/tests/test_cli/test_search.py
index f9335d9..344c923 100644
--- a/tests/test_cli/test_search.py
+++ b/tests/test_cli/test_search.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_search
 from . import utils
diff --git a/tests/test_cli/test_set_build_volume.py b/tests/test_cli/test_set_build_volume.py
index a02c066..23596f0 100644
--- a/tests/test_cli/test_set_build_volume.py
+++ b/tests/test_cli/test_set_build_volume.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_set_build_volume
 from . import utils
 
diff --git a/tests/test_cli/test_set_pkg_arches.py b/tests/test_cli/test_set_pkg_arches.py
index 0d11006..794040d 100644
--- a/tests/test_cli/test_set_pkg_arches.py
+++ b/tests/test_cli/test_set_pkg_arches.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_set_pkg_arches
 from . import utils
diff --git a/tests/test_cli/test_set_pkg_owner.py b/tests/test_cli/test_set_pkg_owner.py
index 5e6acb7..77bda43 100644
--- a/tests/test_cli/test_set_pkg_owner.py
+++ b/tests/test_cli/test_set_pkg_owner.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_set_pkg_owner
 from . import utils
diff --git a/tests/test_cli/test_set_task_priority.py b/tests/test_cli/test_set_task_priority.py
index 98cd03e..61a3144 100644
--- a/tests/test_cli/test_set_task_priority.py
+++ b/tests/test_cli/test_set_task_priority.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_set_task_priority
 from . import utils
diff --git a/tests/test_cli/test_tag_build.py b/tests/test_cli/test_tag_build.py
index 91e300b..ed87776 100644
--- a/tests/test_cli/test_tag_build.py
+++ b/tests/test_cli/test_tag_build.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_tag_build
 from . import utils
 
diff --git a/tests/test_cli/test_taskinfo.py b/tests/test_cli/test_taskinfo.py
index 889506a..684365c 100644
--- a/tests/test_cli/test_taskinfo.py
+++ b/tests/test_cli/test_taskinfo.py
@@ -1,11 +1,14 @@
 from __future__ import absolute_import, print_function
+import collections
 import mock
 import six
-import unittest
-import koji
-import collections
 import time
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
+import koji
 from koji_cli.commands import anon_handle_taskinfo, \
     _printTaskInfo, _parseTaskParams
 
@@ -423,9 +426,9 @@ Finished: Thu Jan  1 00:50:00 1970
 
 """ % tuple('/mnt/koji/work/tasks/2/2/' + k for k in task_output.keys())
 
-        with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout, \
-                mock.patch('time.localtime', new=time.gmtime):
-            _printTaskInfo(session, 1, '/mnt/koji')
+        with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+            with mock.patch('time.localtime', new=time.gmtime):
+                _printTaskInfo(session, 1, '/mnt/koji')
         self.assert_console_message(stdout, expected)
 
     @mock.patch('koji_cli.commands.list_task_output_all_volumes')
@@ -563,9 +566,9 @@ Build: bash-4.4.12-5.fc26 (1)
   Host: kojibuilder
 
 """
-        with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout, \
-                mock.patch('time.localtime', new=time.gmtime):
-            _printTaskInfo(session, 1, '/mnt/koji')
+        with mock.patch('sys.stdout', new_callable=six.StringIO) as stdout:
+            with mock.patch('time.localtime', new=time.gmtime):
+                _printTaskInfo(session, 1, '/mnt/koji')
         self.assert_console_message(stdout, expected)
 
     def test_printTaskInfo_no_task(self):
diff --git a/tests/test_cli/test_unblock_group_pkg.py b/tests/test_cli/test_unblock_group_pkg.py
index 6087041..8cdfe31 100644
--- a/tests/test_cli/test_unblock_group_pkg.py
+++ b/tests/test_cli/test_unblock_group_pkg.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_unblock_group_pkg
 from . import utils
 
diff --git a/tests/test_cli/test_unblock_group_req.py b/tests/test_cli/test_unblock_group_req.py
index 7b7147b..cd88a9c 100644
--- a/tests/test_cli/test_unblock_group_req.py
+++ b/tests/test_cli/test_unblock_group_req.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from koji_cli.commands import handle_unblock_group_req
 from . import utils
 
diff --git a/tests/test_cli/test_unblock_pkg.py b/tests/test_cli/test_unblock_pkg.py
index 105e392..6529c5f 100644
--- a/tests/test_cli/test_unblock_pkg.py
+++ b/tests/test_cli/test_unblock_pkg.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 
 from koji_cli.commands import handle_unblock_pkg
 from . import utils
diff --git a/tests/test_cli/test_unique_path.py b/tests/test_cli/test_unique_path.py
index 247fb3e..6fa0db8 100644
--- a/tests/test_cli/test_unique_path.py
+++ b/tests/test_cli/test_unique_path.py
@@ -1,5 +1,9 @@
 from __future__ import absolute_import
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from six.moves import range
 
 from koji_cli.lib import _unique_path
diff --git a/tests/test_cli/test_upload_progress_callback.py b/tests/test_cli/test_upload_progress_callback.py
index 89cb466..6bcf62f 100644
--- a/tests/test_cli/test_upload_progress_callback.py
+++ b/tests/test_cli/test_upload_progress_callback.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 
 from koji_cli.lib import _format_size, _format_secs, _progress_callback
 
diff --git a/tests/test_cli/test_wait_repo.py b/tests/test_cli/test_wait_repo.py
index 8578979..09e41c9 100644
--- a/tests/test_cli/test_wait_repo.py
+++ b/tests/test_cli/test_wait_repo.py
@@ -1,9 +1,12 @@
 from __future__ import absolute_import
 from __future__ import print_function
+import copy
 import mock
 import six
-import unittest
-import copy
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import anon_handle_wait_repo
 from . import utils
diff --git a/tests/test_cli/test_watch_tasks.py b/tests/test_cli/test_watch_tasks.py
index 310f488..fafcc4d 100644
--- a/tests/test_cli/test_watch_tasks.py
+++ b/tests/test_cli/test_watch_tasks.py
@@ -4,7 +4,10 @@ import mock
 import os
 import six
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
 from six.moves import range
diff --git a/tests/test_cli/test_wrapper_rpm.py b/tests/test_cli/test_wrapper_rpm.py
index fb9559d..f4f83ce 100644
--- a/tests/test_cli/test_wrapper_rpm.py
+++ b/tests/test_cli/test_wrapper_rpm.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from koji_cli.commands import handle_wrapper_rpm
 from . import utils
diff --git a/tests/test_cli/test_write_signed_rpm.py b/tests/test_cli/test_write_signed_rpm.py
index aebd1e1..ad258da 100644
--- a/tests/test_cli/test_write_signed_rpm.py
+++ b/tests/test_cli/test_write_signed_rpm.py
@@ -1,11 +1,14 @@
 from __future__ import absolute_import
+import hashlib
 import mock
 import six
-import unittest
-import koji
-import hashlib
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from mock import call
+import koji
 from koji_cli.commands import handle_write_signed_rpm
 from . import utils
 
diff --git a/tests/test_cli/utils.py b/tests/test_cli/utils.py
index 3e9bb96..2e243ed 100644
--- a/tests/test_cli/utils.py
+++ b/tests/test_cli/utils.py
@@ -1,9 +1,13 @@
 from __future__ import print_function
+import mock
 import os
-import sys
 import six
-import mock
-import unittest
+import sys
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 
 
 """
@@ -174,16 +178,20 @@ class CliTestCase(unittest.TestCase):
         stdout_patch = mock.patch('sys.stdout', new_callable=six.StringIO)
         stderr_patch = mock.patch('sys.stderr', new_callable=six.StringIO)
 
-        with session_patch as session, \
-                stdout_patch as stdout, \
-                stderr_patch as stderr, \
-                self.assertRaises(SystemExit) as cm:
-            callableObj(*test_args, **test_kwargs)
+        with session_patch as session:
+            with stdout_patch as stdout:
+                with stderr_patch as stderr:
+                    with self.assertRaises(SystemExit) as cm:
+                        callableObj(*test_args, **test_kwargs)
         session.assert_called_once()
         self.assert_console_message(stdout, **message['stdout'])
         self.assert_console_message(stderr, **message['stderr'])
         assert_function()
-        self.assertEqual(cm.exception.code, exit_code)
+        if isinstance(cm.exception, int):
+            # python 2.6.6
+            self.assertEqual(cm.exception, exit_code)
+        else:
+            self.assertEqual(cm.exception.code, exit_code)
 
     @mock.patch('koji_cli.commands.activate_session')
     def assert_help(self, callableObj, message, activate_session_mock):
diff --git a/tests/test_docs_version.py b/tests/test_docs_version.py
index 21beb85..db8e617 100644
--- a/tests/test_docs_version.py
+++ b/tests/test_docs_version.py
@@ -1,12 +1,16 @@
 import os
 import subprocess
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 # docs version lives in docs/source/conf.py
 TOPDIR = os.path.dirname(__file__) + '/..'
 SPHINX_CONF = TOPDIR + '/docs/source/conf.py'
 
 import imp
+import os
 sphinx_conf = imp.load_source('sphinx_conf', SPHINX_CONF)
 
 
@@ -18,7 +22,8 @@ class TestDocsVersion(unittest.TestCase):
     def get_koji_version(self):
         spec = self.get_spec()
         cmd = ['rpm', '-q', '--specfile', spec, '--qf', '%{version}\\n']
-        output = subprocess.check_output(cmd)
+        popen = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+        output = popen.stdout.read()
         # rpm outputs a line for each subpackage
         version = output.splitlines()[0]
         return version
diff --git a/tests/test_hub/test_add_btype.py b/tests/test_hub/test_add_btype.py
index e64cc0f..eef3d2d 100644
--- a/tests/test_hub/test_add_btype.py
+++ b/tests/test_hub/test_add_btype.py
@@ -1,4 +1,7 @@
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import mock
 
 import koji
diff --git a/tests/test_hub/test_add_external_rpm.py b/tests/test_hub/test_add_external_rpm.py
index 7aa928b..874aff1 100644
--- a/tests/test_hub/test_add_external_rpm.py
+++ b/tests/test_hub/test_add_external_rpm.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_add_host.py b/tests/test_hub/test_add_host.py
index ce0cf43..34c51b1 100644
--- a/tests/test_hub/test_add_host.py
+++ b/tests/test_hub/test_add_host.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_add_host_to_channel.py b/tests/test_hub/test_add_host_to_channel.py
index 7a7792d..3ca1036 100644
--- a/tests/test_hub/test_add_host_to_channel.py
+++ b/tests/test_hub/test_add_host_to_channel.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_apply_query_opts.py b/tests/test_hub/test_apply_query_opts.py
index 653723c..8e78090 100644
--- a/tests/test_hub/test_apply_query_opts.py
+++ b/tests/test_hub/test_apply_query_opts.py
@@ -1,6 +1,8 @@
 import copy
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 from nose.tools import eq_
 
 import kojihub
diff --git a/tests/test_hub/test_cg_importer.py b/tests/test_hub/test_cg_importer.py
index ac0e528..8c82551 100644
--- a/tests/test_hub/test_cg_importer.py
+++ b/tests/test_hub/test_cg_importer.py
@@ -1,7 +1,10 @@
-import unittest
 import mock
 import os
 import shutil
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_check_volume_policy.py b/tests/test_hub/test_check_volume_policy.py
index e8c9843..8271cec 100644
--- a/tests/test_hub/test_check_volume_policy.py
+++ b/tests/test_hub/test_check_volume_policy.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import koji.policy
 import kojihub
diff --git a/tests/test_hub/test_complete_image_build.py b/tests/test_hub/test_complete_image_build.py
index 0f67b15..646032a 100644
--- a/tests/test_hub/test_complete_image_build.py
+++ b/tests/test_hub/test_complete_image_build.py
@@ -5,8 +5,10 @@ import os
 import os.path
 import shutil
 import tempfile
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import koji.util
 import kojihub
@@ -160,9 +162,9 @@ class TestCompleteImageBuild(unittest.TestCase):
             return old_ip(table, *a, **kw)
         def my_ga(archive_id, **kw):
             return share['archiveinfo']
-        with mock.patch('kojihub.InsertProcessor', new=my_ip), \
-                    mock.patch('kojihub.get_archive', new=my_ga):
-            return orig_import_archive_internal(*a, **kw)
+        with mock.patch('kojihub.InsertProcessor', new=my_ip):
+            with mock.patch('kojihub.get_archive', new=my_ga):
+                return orig_import_archive_internal(*a, **kw)
 
     def set_up_callbacks(self):
         new_callbacks = copy.deepcopy(koji.plugin.callbacks)
diff --git a/tests/test_hub/test_complete_maven_build.py b/tests/test_hub/test_complete_maven_build.py
index b46a0fc..2bd7419 100644
--- a/tests/test_hub/test_complete_maven_build.py
+++ b/tests/test_hub/test_complete_maven_build.py
@@ -5,8 +5,10 @@ import os
 import os.path
 import shutil
 import tempfile
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import koji.util
 import kojihub
@@ -94,9 +96,9 @@ class TestCompleteMavenBuild(unittest.TestCase):
             return mock.MagicMock()
         def my_ga(archive_id, **kw):
             return share['archiveinfo']
-        with mock.patch('kojihub.InsertProcessor', new=my_ip), \
-                    mock.patch('kojihub.get_archive', new=my_ga):
-            orig_import_archive_internal(*a, **kw)
+        with mock.patch('kojihub.InsertProcessor', new=my_ip):
+            with mock.patch('kojihub.get_archive', new=my_ga):
+                orig_import_archive_internal(*a, **kw)
 
     def set_up_callbacks(self):
         new_callbacks = copy.deepcopy(koji.plugin.callbacks)
diff --git a/tests/test_hub/test_create_tag.py b/tests/test_hub/test_create_tag.py
index 91dea25..d0a3765 100644
--- a/tests/test_hub/test_create_tag.py
+++ b/tests/test_hub/test_create_tag.py
@@ -2,8 +2,10 @@ import copy
 import mock
 import shutil
 import tempfile
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_delete_build.py b/tests/test_hub/test_delete_build.py
index 2cd2dae..c46207b 100644
--- a/tests/test_hub/test_delete_build.py
+++ b/tests/test_hub/test_delete_build.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import kojihub
 import time
 from koji import GenericError
diff --git a/tests/test_hub/test_delete_tag.py b/tests/test_hub/test_delete_tag.py
index 76875e2..832cece 100644
--- a/tests/test_hub/test_delete_tag.py
+++ b/tests/test_hub/test_delete_tag.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_dist_repo.py b/tests/test_hub/test_dist_repo.py
index 90f9d54..272b3f5 100644
--- a/tests/test_hub/test_dist_repo.py
+++ b/tests/test_hub/test_dist_repo.py
@@ -1,5 +1,7 @@
-
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import json
 import mock
 import os
diff --git a/tests/test_hub/test_edit_host.py b/tests/test_hub/test_edit_host.py
index 6759a5a..8b81547 100644
--- a/tests/test_hub/test_edit_host.py
+++ b/tests/test_hub/test_edit_host.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_edit_tag.py b/tests/test_hub/test_edit_tag.py
index 65d6dc6..e011267 100644
--- a/tests/test_hub/test_edit_tag.py
+++ b/tests/test_hub/test_edit_tag.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_getRPMDeps.py b/tests/test_hub/test_getRPMDeps.py
index f4931a4..e6a64e8 100644
--- a/tests/test_hub/test_getRPMDeps.py
+++ b/tests/test_hub/test_getRPMDeps.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import
 import mock
 import os
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_get_active_repos.py b/tests/test_hub/test_get_active_repos.py
index da6c325..eb67a57 100644
--- a/tests/test_hub/test_get_active_repos.py
+++ b/tests/test_hub/test_get_active_repos.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 import koji.db
diff --git a/tests/test_hub/test_get_archive_file.py b/tests/test_hub/test_get_archive_file.py
index 466e31d..b3a4b9b 100644
--- a/tests/test_hub/test_get_archive_file.py
+++ b/tests/test_hub/test_get_archive_file.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_get_build_logs.py b/tests/test_hub/test_get_build_logs.py
index 88157aa..f0b8ebc 100644
--- a/tests/test_hub/test_get_build_logs.py
+++ b/tests/test_hub/test_get_build_logs.py
@@ -2,8 +2,10 @@ import mock
 import os
 import shutil
 import tempfile
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_get_build_type.py b/tests/test_hub/test_get_build_type.py
index b4013e9..7cd03f1 100644
--- a/tests/test_hub/test_get_build_type.py
+++ b/tests/test_hub/test_get_build_type.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_get_host.py b/tests/test_hub/test_get_host.py
index 70d7487..f5ea774 100644
--- a/tests/test_hub/test_get_host.py
+++ b/tests/test_hub/test_get_host.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_get_next_release.py b/tests/test_hub/test_get_next_release.py
index adfeea3..7b69dec 100644
--- a/tests/test_hub/test_get_next_release.py
+++ b/tests/test_hub/test_get_next_release.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_get_upload_path.py b/tests/test_hub/test_get_upload_path.py
index a1191ce..cb88aa4 100644
--- a/tests/test_hub/test_get_upload_path.py
+++ b/tests/test_hub/test_get_upload_path.py
@@ -1,7 +1,11 @@
 import os
 import mock
 import shutil
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import kojihub
 from koji import GenericError
 
diff --git a/tests/test_hub/test_get_user_perms.py b/tests/test_hub/test_get_user_perms.py
index 5112083..ffad733 100644
--- a/tests/test_hub/test_get_user_perms.py
+++ b/tests/test_hub/test_get_user_perms.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_get_verify_class.py b/tests/test_hub/test_get_verify_class.py
index ae94ed6..84adc82 100644
--- a/tests/test_hub/test_get_verify_class.py
+++ b/tests/test_hub/test_get_verify_class.py
@@ -1,4 +1,8 @@
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import kojihub
 from koji import GenericError
 from koji.util import md5_constructor, adler32_constructor
diff --git a/tests/test_hub/test_group_operations.py b/tests/test_hub/test_group_operations.py
index c62cab4..c5e07c3 100644
--- a/tests/test_hub/test_group_operations.py
+++ b/tests/test_hub/test_group_operations.py
@@ -1,6 +1,8 @@
 import mock
-import unittest
-
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import koji
 import kojihub
 
diff --git a/tests/test_hub/test_import_build.py b/tests/test_hub/test_import_build.py
index 03ca6fe..783eea0 100644
--- a/tests/test_hub/test_import_build.py
+++ b/tests/test_hub/test_import_build.py
@@ -2,7 +2,10 @@ import copy
 import mock
 import shutil
 import tempfile
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_import_image_internal.py b/tests/test_hub/test_import_image_internal.py
index 75dedf4..62ad108 100644
--- a/tests/test_hub/test_import_image_internal.py
+++ b/tests/test_hub/test_import_image_internal.py
@@ -1,13 +1,15 @@
-import unittest
 import mock
 import os
 import shutil
 import tempfile
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
 
-
 class TestImportImageInternal(unittest.TestCase):
     def setUp(self):
         self.tempdir = tempfile.mkdtemp()
diff --git a/tests/test_hub/test_insert_processor.py b/tests/test_hub/test_insert_processor.py
index 1771681..b661bf5 100644
--- a/tests/test_hub/test_insert_processor.py
+++ b/tests/test_hub/test_insert_processor.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_list_archive_files.py b/tests/test_hub/test_list_archive_files.py
index 5f05df1..46d95d9 100644
--- a/tests/test_hub/test_list_archive_files.py
+++ b/tests/test_hub/test_list_archive_files.py
@@ -1,6 +1,8 @@
-import unittest
-
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_list_btypes.py b/tests/test_hub/test_list_btypes.py
index b5f4bc5..147444b 100644
--- a/tests/test_hub/test_list_btypes.py
+++ b/tests/test_hub/test_list_btypes.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_list_channels.py b/tests/test_hub/test_list_channels.py
index ee4e68f..3746b86 100644
--- a/tests/test_hub/test_list_channels.py
+++ b/tests/test_hub/test_list_channels.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_list_hosts.py b/tests/test_hub/test_list_hosts.py
index 8b09295..e13e38f 100644
--- a/tests/test_hub/test_list_hosts.py
+++ b/tests/test_hub/test_list_hosts.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_list_task_output.py b/tests/test_hub/test_list_task_output.py
index 0b27af1..7da39ea 100644
--- a/tests/test_hub/test_list_task_output.py
+++ b/tests/test_hub/test_list_task_output.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_listing.py b/tests/test_hub/test_listing.py
index a39f2b0..9587fd1 100644
--- a/tests/test_hub/test_listing.py
+++ b/tests/test_hub/test_listing.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_models/test_host.py b/tests/test_hub/test_models/test_host.py
index c1bc6e5..e94ac0d 100644
--- a/tests/test_hub/test_models/test_host.py
+++ b/tests/test_hub/test_models/test_host.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_new_typed_build.py b/tests/test_hub/test_new_typed_build.py
index a1ae47f..f93f84e 100644
--- a/tests/test_hub/test_new_typed_build.py
+++ b/tests/test_hub/test_new_typed_build.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_notifications.py b/tests/test_hub/test_notifications.py
index 1608260..269ef8a 100644
--- a/tests/test_hub/test_notifications.py
+++ b/tests/test_hub/test_notifications.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_policy_tests.py b/tests/test_hub/test_policy_tests.py
index 543863a..7d114fc 100644
--- a/tests/test_hub/test_policy_tests.py
+++ b/tests/test_hub/test_policy_tests.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_query_processor.py b/tests/test_hub/test_query_processor.py
index 7b229bd..8e1464f 100644
--- a/tests/test_hub/test_query_processor.py
+++ b/tests/test_hub/test_query_processor.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_remove_host_from_channel.py b/tests/test_hub/test_remove_host_from_channel.py
index f2f31af..cb3d111 100644
--- a/tests/test_hub/test_remove_host_from_channel.py
+++ b/tests/test_hub/test_remove_host_from_channel.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_rpmdiff.py b/tests/test_hub/test_rpmdiff.py
index f8bae3e..fcc1280 100644
--- a/tests/test_hub/test_rpmdiff.py
+++ b/tests/test_hub/test_rpmdiff.py
@@ -1,6 +1,9 @@
 import copy
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_set_host_enabled.py b/tests/test_hub/test_set_host_enabled.py
index 558b66f..698e451 100644
--- a/tests/test_hub/test_set_host_enabled.py
+++ b/tests/test_hub/test_set_host_enabled.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_tag_operations.py b/tests/test_hub/test_tag_operations.py
index 2f0d10c..fbd5cfb 100644
--- a/tests/test_hub/test_tag_operations.py
+++ b/tests/test_hub/test_tag_operations.py
@@ -2,7 +2,10 @@ import copy
 import mock
 import shutil
 import tempfile
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_task_wait_results.py b/tests/test_hub/test_task_wait_results.py
index 332293e..a454038 100644
--- a/tests/test_hub/test_task_wait_results.py
+++ b/tests/test_hub/test_task_wait_results.py
@@ -1,6 +1,9 @@
 import mock
-import unittest
 import xmlrpclib
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_update_processor.py b/tests/test_hub/test_update_processor.py
index e765b3b..83fcaa6 100644
--- a/tests/test_hub/test_update_processor.py
+++ b/tests/test_hub/test_update_processor.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_hub/test_user_groups.py b/tests/test_hub/test_user_groups.py
index 4853560..0d06e15 100644
--- a/tests/test_hub/test_user_groups.py
+++ b/tests/test_hub/test_user_groups.py
@@ -1,5 +1,8 @@
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import kojihub
diff --git a/tests/test_hub/test_write_maven_repo_metadata.py b/tests/test_hub/test_write_maven_repo_metadata.py
index 7676d3d..d990e68 100644
--- a/tests/test_hub/test_write_maven_repo_metadata.py
+++ b/tests/test_hub/test_write_maven_repo_metadata.py
@@ -1,9 +1,11 @@
-from __future__ import absolute_import
-from __future__ import print_function
-import unittest
+from __future__ import absolute_import, with_statement
 import mock
 import os
 import datetime
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 from kojihub import _write_maven_repo_metadata
@@ -29,10 +31,10 @@ class TestWriteMavenRepoMetadata(unittest.TestCase):
         artifacts.add(('0', '1', '1.3.11'))
 
         now = datetime.datetime.now()
-        with mock.patch('kojihub.open', create=True) as openf_mock, \
-                mock.patch('datetime.datetime') as datetime_mock:
-            datetime_mock.now.return_value = now
-            _write_maven_repo_metadata(destdir, artifacts)
+        with mock.patch('kojihub.open', create=True) as openf_mock:
+            with mock.patch('datetime.datetime') as datetime_mock:
+                datetime_mock.now.return_value = now
+                _write_maven_repo_metadata(destdir, artifacts)
 
         openf_mock.assert_called_with(
             os.path.join(destdir, 'maven-metadata.xml'), 'w')
diff --git a/tests/test_hub/utils.py b/tests/test_hub/utils.py
index 1e14b6e..b1cf635 100644
--- a/tests/test_hub/utils.py
+++ b/tests/test_hub/utils.py
@@ -1,6 +1,9 @@
-import unittest
 import mock
 import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import kojihub
 
diff --git a/tests/test_kojira/test_repo_manager.py b/tests/test_kojira/test_repo_manager.py
index 09b5bf1..e4c34cd 100644
--- a/tests/test_kojira/test_repo_manager.py
+++ b/tests/test_kojira/test_repo_manager.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import time
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_argspec.py b/tests/test_lib/test_argspec.py
index 14b536a..29df33c 100644
--- a/tests/test_lib/test_argspec.py
+++ b/tests/test_lib/test_argspec.py
@@ -1,4 +1,8 @@
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import koji.util
 
 class TestApplyArgspec(unittest.TestCase):
diff --git a/tests/test_lib/test_client_session.py b/tests/test_lib/test_client_session.py
index 961421a..8613bd0 100644
--- a/tests/test_lib/test_client_session.py
+++ b/tests/test_lib/test_client_session.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
-import unittest
 import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_encode_datetime.py b/tests/test_lib/test_encode_datetime.py
index 1583c37..8d931df 100644
--- a/tests/test_lib/test_encode_datetime.py
+++ b/tests/test_lib/test_encode_datetime.py
@@ -1,5 +1,8 @@
 import datetime
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji.util
 from koji.xmlrpcplus import DateTime
diff --git a/tests/test_lib/test_fixEncoding.py b/tests/test_lib/test_fixEncoding.py
index 267f53d..0388a99 100644
--- a/tests/test_lib/test_fixEncoding.py
+++ b/tests/test_lib/test_fixEncoding.py
@@ -5,9 +5,13 @@
 
 from __future__ import absolute_import
 import koji
-import six
-import unittest
 import mock
+import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 
 class FixEncodingTestCase(unittest.TestCase):
     """Main test case container"""
diff --git a/tests/test_lib/test_format_time.py b/tests/test_lib/test_format_time.py
index f989aa4..91ae9ab 100644
--- a/tests/test_lib/test_format_time.py
+++ b/tests/test_lib/test_format_time.py
@@ -1,6 +1,10 @@
 from __future__ import absolute_import
 import datetime
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import six.moves.xmlrpc_client as xmlrpc_client
 
 from koji import formatTime, formatTimeLong
diff --git a/tests/test_lib/test_gen_mock_config.py b/tests/test_lib/test_gen_mock_config.py
index 9afe1a0..35bae4f 100644
--- a/tests/test_lib/test_gen_mock_config.py
+++ b/tests/test_lib/test_gen_mock_config.py
@@ -1,7 +1,10 @@
 import ast
 import os
 import os.path
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_grab_session_options.py b/tests/test_lib/test_grab_session_options.py
index 98d2f7f..434db26 100644
--- a/tests/test_lib/test_grab_session_options.py
+++ b/tests/test_lib/test_grab_session_options.py
@@ -1,6 +1,9 @@
 from __future__ import absolute_import
-import unittest
 import optparse
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_gssapi.py b/tests/test_lib/test_gssapi.py
index ebdefe6..cc2dff3 100644
--- a/tests/test_lib/test_gssapi.py
+++ b/tests/test_lib/test_gssapi.py
@@ -1,9 +1,11 @@
 from __future__ import absolute_import
 
-import os
-import unittest
-
 import mock
+import os
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_parsers.py b/tests/test_lib/test_parsers.py
index fc3b164..93365c5 100644
--- a/tests/test_lib/test_parsers.py
+++ b/tests/test_lib/test_parsers.py
@@ -6,7 +6,10 @@ from __future__ import absolute_import
 import mock
 import os
 import rpm
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib/test_plugin.py b/tests/test_lib/test_plugin.py
index f064a5d..6c69cd5 100644
--- a/tests/test_lib/test_plugin.py
+++ b/tests/test_lib/test_plugin.py
@@ -1,7 +1,10 @@
 import copy
 import datetime
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import koji.util
diff --git a/tests/test_lib/test_profiles.py b/tests/test_lib/test_profiles.py
index 0417023..b29f1b2 100644
--- a/tests/test_lib/test_profiles.py
+++ b/tests/test_lib/test_profiles.py
@@ -1,6 +1,4 @@
 from __future__ import absolute_import
-import unittest
-
 import koji
 import sys
 import threading
@@ -8,6 +6,11 @@ import traceback
 from six.moves import range
 import six
 
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 # XXX remove skip when Fedora bug is fixed
 @unittest.skipIf(six.PY3, "coverage bug Fedora, see rhbz#1452339")
 class ProfilesTestCase(unittest.TestCase):
diff --git a/tests/test_lib/test_utils.py b/tests/test_lib/test_utils.py
index 226534a..23e1bbb 100644
--- a/tests/test_lib/test_utils.py
+++ b/tests/test_lib/test_utils.py
@@ -1,16 +1,19 @@
 # coding=utf-8
 from __future__ import absolute_import
+import calendar
 import mock
-import unittest
-from mock import call, patch
-from datetime import datetime
-
+import optparse
 import os
-import time
 import resource
-import optparse
-import calendar
 import six.moves.configparser
+import time
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+from mock import call, patch
+from datetime import datetime
 import koji
 import koji.util
 
@@ -450,27 +453,27 @@ class MavenUtilTestCase(unittest.TestCase):
     def test_tsort(self):
         # success, one path
         parts = {
-            'p1': {'p2', 'p3'},
-            'p2': {'p3'},
+            'p1': set(['p2', 'p3']),
+            'p2': set(['p3']),
             'p3': set()
         }
         self.assertEqual(koji.util.tsort(parts),
-                         [{'p3'}, {'p2'}, {'p1'}])
+                         [set(['p3']), set(['p2']), set(['p1'])])
         # success, multi-path
         parts = {
-            'p1': {'p2'},
-            'p2': {'p4'},
-            'p3': {'p4'},
+            'p1': set(['p2']),
+            'p2': set(['p4']),
+            'p3': set(['p4']),
             'p4': set(),
             'p5': set()
         }
         self.assertEqual(koji.util.tsort(parts),
-                         [{'p4', 'p5'}, {'p2', 'p3'}, {'p1'}])
+                         [set(['p4', 'p5']), set(['p2', 'p3']), set(['p1'])])
         # failed, missing child 'p4'
         parts = {
-            'p1': {'p2'},
-            'p2': {'p3'},
-            'p3': {'p4'}
+            'p1': set(['p2']),
+            'p2': set(['p3']),
+            'p3': set(['p4'])
         }
         with self.assertRaises(ValueError) as cm:
             koji.util.tsort(parts)
@@ -478,9 +481,9 @@ class MavenUtilTestCase(unittest.TestCase):
 
         # failed, circular
         parts = {
-            'p1': {'p2'},
-            'p2': {'p3'},
-            'p3': {'p1'}
+            'p1': set(['p2']),
+            'p2': set(['p3']),
+            'p3': set(['p1'])
         }
         with self.assertRaises(ValueError) as cm:
             koji.util.tsort(parts)
@@ -624,17 +627,17 @@ class MavenUtilTestCase(unittest.TestCase):
 
     def test_isSuccess(self):
         """Test isSuccess function"""
-        with mock.patch('os.WIFEXITED') as m_exit, \
-                mock.patch('os.WEXITSTATUS') as m_exitst:
-            # True case
-            m_exit.return_value, m_exitst.return_value = True, 0
-            self.assertTrue(koji.util.isSuccess(0))
-
-            # False cases
-            m_exit.return_value, m_exitst.return_value = True, 1
-            self.assertFalse(koji.util.isSuccess(0))
-            m_exit.return_value, m_exitst.return_value = False, 255
-            self.assertFalse(koji.util.isSuccess(0))
+        with mock.patch('os.WIFEXITED') as m_exit:
+            with mock.patch('os.WEXITSTATUS') as m_exitst:
+                # True case
+                m_exit.return_value, m_exitst.return_value = True, 0
+                self.assertTrue(koji.util.isSuccess(0))
+
+                # False cases
+                m_exit.return_value, m_exitst.return_value = True, 1
+                self.assertFalse(koji.util.isSuccess(0))
+                m_exit.return_value, m_exitst.return_value = False, 255
+                self.assertFalse(koji.util.isSuccess(0))
 
     def test_call_with_argcheck(self):
         """Test call_wit_argcheck function"""
@@ -899,7 +902,7 @@ class MavenUtilTestCase(unittest.TestCase):
                }
 
         # create a resource token <--> id lookup table
-        rlimit_lookup = {getattr(resource, k): k for k in options}
+        rlimit_lookup = dict([(getattr(resource, k), k) for k in options])
 
         def _getrlimit(res):
             return (options.get(rlimit_lookup[res], None), 0)
@@ -907,47 +910,47 @@ class MavenUtilTestCase(unittest.TestCase):
         def _setrlimit(res, limits):
             results[rlimit_lookup[res]] = str(limits[0])
 
-        results = {k: '' for k, v in options.items()}
-        with mock.patch('resource.setrlimit') as m_set, \
-                mock.patch('resource.getrlimit') as m_get:
-            m_get.side_effect = ValueError('resource.getrlimit-value-error')
-            six.assertRaisesRegex(self, ValueError, 'resource.getrlimit-value-error',
-                                  koji.util.setup_rlimits, options, logger)
-
-            m_get.side_effect = _getrlimit
-
-            # logger.error test
-            koji.util.setup_rlimits({'RLIMIT_AS': 'abcde'}, logger)
-            logger.error.assert_called_with('Invalid resource limit: %s=%s',
-                                            'RLIMIT_AS',
-                                            'abcde')
-
-            koji.util.setup_rlimits({'RLIMIT_AS': '1 2 3 4 5'}, logger)
-            logger.error.assert_called_with('Invalid resource limit: %s=%s',
-                                            'RLIMIT_AS',
-                                            '1 2 3 4 5')
-
-            # exception and logger.error test
-            m_set.side_effect = ValueError('resource.setrlimit-value-error')
-            koji.util.setup_rlimits({'RLIMIT_AS': '0'}, logger)
-            logger.error.assert_called_with('Unable to set %s: %s',
-                                            'RLIMIT_AS',
-                                            m_set.side_effect)
-
-            # run setrlimit test, the results should be equal to options
-            m_set.side_effect = _setrlimit
-
-            # make some noise in options
-            test_opt = dict(options)
-            test_opt.update({
-                'RLIMIT_CUSTOM':  'fake_rlimit_key',
-                'DBName':         'koji',
-                'DBUser':         'koji',
-                'KojiDir':        '/mnt/koji',
-                'KojiDebug':      True})
-
-            koji.util.setup_rlimits(test_opt, logger)
-            six.assertCountEqual(self, results, options)
+        results = dict([(k, '') for k in options])
+        with mock.patch('resource.setrlimit') as m_set:
+            with mock.patch('resource.getrlimit') as m_get:
+                m_get.side_effect = ValueError('resource.getrlimit-value-error')
+                six.assertRaisesRegex(self, ValueError, 'resource.getrlimit-value-error',
+                                      koji.util.setup_rlimits, options, logger)
+
+                m_get.side_effect = _getrlimit
+
+                # logger.error test
+                koji.util.setup_rlimits({'RLIMIT_AS': 'abcde'}, logger)
+                logger.error.assert_called_with('Invalid resource limit: %s=%s',
+                                                'RLIMIT_AS',
+                                                'abcde')
+
+                koji.util.setup_rlimits({'RLIMIT_AS': '1 2 3 4 5'}, logger)
+                logger.error.assert_called_with('Invalid resource limit: %s=%s',
+                                                'RLIMIT_AS',
+                                                '1 2 3 4 5')
+
+                # exception and logger.error test
+                m_set.side_effect = ValueError('resource.setrlimit-value-error')
+                koji.util.setup_rlimits({'RLIMIT_AS': '0'}, logger)
+                logger.error.assert_called_with('Unable to set %s: %s',
+                                                'RLIMIT_AS',
+                                                m_set.side_effect)
+
+                # run setrlimit test, the results should be equal to options
+                m_set.side_effect = _setrlimit
+
+                # make some noise in options
+                test_opt = dict(options)
+                test_opt.update({
+                    'RLIMIT_CUSTOM':  'fake_rlimit_key',
+                    'DBName':         'koji',
+                    'DBUser':         'koji',
+                    'KojiDir':        '/mnt/koji',
+                    'KojiDebug':      True})
+
+                koji.util.setup_rlimits(test_opt, logger)
+                six.assertCountEqual(self, results, options)
 
     def test_adler32_constructor(self):
         """Test adler32_constructor function"""
diff --git a/tests/test_lib/test_xmlrpcplus.py b/tests/test_lib/test_xmlrpcplus.py
index 70aa7f5..239900c 100644
--- a/tests/test_lib/test_xmlrpcplus.py
+++ b/tests/test_lib/test_xmlrpcplus.py
@@ -1,5 +1,8 @@
 # coding=utf-8
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from six.moves import xmlrpc_client
 from koji import xmlrpcplus
diff --git a/tests/test_lib_py2only/test_auth.py b/tests/test_lib_py2only/test_auth.py
index 49b4b38..0ee45a9 100644
--- a/tests/test_lib_py2only/test_auth.py
+++ b/tests/test_lib_py2only/test_auth.py
@@ -1,6 +1,9 @@
 from __future__ import absolute_import
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import koji.auth
diff --git a/tests/test_lib_py2only/test_krbv.py b/tests/test_lib_py2only/test_krbv.py
index d5fa4ee..47e6943 100644
--- a/tests/test_lib_py2only/test_krbv.py
+++ b/tests/test_lib_py2only/test_krbv.py
@@ -1,11 +1,13 @@
 from __future__ import absolute_import
 
 import base64
-import six
-import unittest
-
 # This is python-mock, not the rpm mock tool we know and love
 import mock
+import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_lib_py2only/test_policy.py b/tests/test_lib_py2only/test_policy.py
index d228df7..661fda3 100644
--- a/tests/test_lib_py2only/test_policy.py
+++ b/tests/test_lib_py2only/test_policy.py
@@ -1,5 +1,8 @@
 from __future__ import absolute_import
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from nose.tools import raises
 
diff --git a/tests/test_lib_py2only/test_restart_tasks.py b/tests/test_lib_py2only/test_restart_tasks.py
index bfe7b67..ac8d1e4 100644
--- a/tests/test_lib_py2only/test_restart_tasks.py
+++ b/tests/test_lib_py2only/test_restart_tasks.py
@@ -1,7 +1,10 @@
 import mock
 import shutil
 import tempfile
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji.tasks
 
diff --git a/tests/test_lib_py2only/test_tasks.py b/tests/test_lib_py2only/test_tasks.py
index 18cf398..05290fe 100644
--- a/tests/test_lib_py2only/test_tasks.py
+++ b/tests/test_lib_py2only/test_tasks.py
@@ -1,16 +1,20 @@
 from __future__ import absolute_import
 import random
 import shutil
+import six
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from os import path, makedirs
 from tempfile import gettempdir
-from unittest import TestCase
 from mock import patch, MagicMock, Mock, call
 
 import koji
 from koji.tasks import BaseTaskHandler, FakeTask, ForkTask, SleepTask, \
                        WaitTestTask, scan_mounts, umount_all, \
                        safe_rmtree
-import six
 
 
 def get_fake_mounts_file():
@@ -68,7 +72,7 @@ class BadTask(BaseTaskHandler):
     Methods = ['some_method']
 
 
-class TasksTestCase(TestCase):
+class TasksTestCase(unittest.TestCase):
 
     def tearDown(self):
         temp_dir_root = get_temp_dir_root()
@@ -700,7 +704,7 @@ class TasksTestCase(TestCase):
         # will be skipped as 'canfail'
         obj.session.getTaskResult.assert_has_calls([call(3)])
 
-class TestSafeRmtree(TestCase):
+class TestSafeRmtree(unittest.TestCase):
     @patch('os.path.exists', return_value=True)
     @patch('os.path.isfile', return_value=True)
     @patch('os.path.islink', return_value=False)
diff --git a/tests/test_plugins/test_protonmsg.py b/tests/test_plugins/test_protonmsg.py
index 9d51e97..ed26f64 100644
--- a/tests/test_plugins/test_protonmsg.py
+++ b/tests/test_plugins/test_protonmsg.py
@@ -1,9 +1,13 @@
 import six
-import unittest
-from mock import patch, MagicMock
 import protonmsg
-from koji.context import context
 import tempfile
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+from mock import patch, MagicMock
+from koji.context import context
 from ConfigParser import SafeConfigParser
 
 class TestProtonMsg(unittest.TestCase):
diff --git a/tests/test_plugins/test_runroot_builder.py b/tests/test_plugins/test_runroot_builder.py
index 426ad35..496a5ad 100644
--- a/tests/test_plugins/test_runroot_builder.py
+++ b/tests/test_plugins/test_runroot_builder.py
@@ -1,7 +1,11 @@
 from __future__ import absolute_import
 import copy
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 import six.moves.configparser
 
 # inject builder data
@@ -12,6 +16,13 @@ __main__.BuildRoot = kojid.BuildRoot
 import koji
 import runroot
 
+def mock_open():
+    """Return the right patch decorator for open"""
+    if six.PY2:
+        return mock.patch('__builtin__.open')
+    else:
+        return mock.patch('builtins.open')
+
 
 CONFIG1 = {
         'paths': {
@@ -95,7 +106,7 @@ class TestRunrootConfig(unittest.TestCase):
         options.workdir = '/tmp/nonexistentdirectory'
         with self.assertRaises(koji.GenericError) as cm:
             runroot.RunRootTask(123, 'runroot', {}, session, options)
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
             "bad config: missing options in path0 section")
 
     @mock.patch('ConfigParser.SafeConfigParser')
@@ -108,7 +119,7 @@ class TestRunrootConfig(unittest.TestCase):
         options.workdir = '/tmp/nonexistentdirectory'
         with self.assertRaises(koji.GenericError) as cm:
             runroot.RunRootTask(123, 'runroot', {}, session, options)
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
             "bad config: all paths (default_mounts, safe_roots, path_subs) needs to be absolute: ")
 
     @mock.patch('ConfigParser.SafeConfigParser')
@@ -178,10 +189,10 @@ class TestMounts(unittest.TestCase):
         self.assertEqual(self.t._get_path_params('/mnt/archive', 'rw'),
             ('archive.org:/vol/archive/', '/mnt/archive', 'nfs', 'rw,hard,intr,nosuid,nodev,noatime,tcp'))
 
+    @mock_open()
     @mock.patch('os.path.isdir')
-    @mock.patch('runroot.open')
     @mock.patch('runroot.log_output')
-    def test_do_mounts(self, log_output, file_mock, is_dir):
+    def test_do_mounts(self, log_output, is_dir, open_mock):
         log_output.return_value = 0 # successful mount
 
         # no mounts, don't do anything
@@ -192,7 +203,7 @@ class TestMounts(unittest.TestCase):
         # mountpoint has no absolute_path
         with self.assertRaises(koji.GenericError) as cm:
             self.t.do_mounts('rootdir', [('nfs:nfs', 'relative_path', 'nfs', '')])
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
                 "invalid mount point: relative_path")
 
         # cover missing opts
@@ -215,7 +226,7 @@ class TestMounts(unittest.TestCase):
         mounts = [self.t._get_path_params('/mnt/archive')]
         with self.assertRaises(koji.GenericError) as cm:
             self.t.do_mounts('rootdir', mounts)
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
             'Unable to mount rootdir/mnt/archive: mount -t nfs -o'
             ' ro,hard,intr,nosuid,nodev,noatime,tcp archive.org:/vol/archive/'
             ' rootdir/mnt/archive was killed by signal 1')
@@ -239,7 +250,7 @@ class TestMounts(unittest.TestCase):
         is_dir.return_value = False
         with self.assertRaises(koji.GenericError) as cm:
             self.t.do_mounts('rootdir', [mount])
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
             "No such directory or mount: archive.org:/vol/archive/")
 
         # bg option forbidden
@@ -249,7 +260,7 @@ class TestMounts(unittest.TestCase):
         is_dir.return_value = False
         with self.assertRaises(koji.GenericError) as cm:
             self.t.do_mounts('rootdir', [mount])
-        self.assertEqual(cm.exception.message,
+        self.assertEqual(cm.exception.args[0],
             "bad config: background mount not allowed")
 
     def test_do_extra_mounts(self):
@@ -279,19 +290,20 @@ class TestMounts(unittest.TestCase):
         self.t.do_mounts.assert_not_called()
 
 
+    @mock_open()
     @mock.patch('runroot.scan_mounts')
     @mock.patch('os.unlink')
     @mock.patch('commands.getstatusoutput')
     @mock.patch('os.path.exists')
-    def test_undo_mounts(self, path_exists, getstatusoutput, os_unlink, scan_mounts):
+    def test_undo_mounts(self, path_exists, getstatusoutput, os_unlink, scan_mounts, m_open):
         self.t.logger = mock.MagicMock()
         scan_mounts.return_value = ['mount_1', 'mount_2']
 
         # correct
         getstatusoutput.return_value = (0, 'ok')
         path_exists.return_value = True
-        with mock.patch('runroot.open', mock.mock_open(read_data = 'mountpoint')):
-            self.t.undo_mounts('rootdir')
+        m_open.return_value.__enter__.return_value.readlines.return_value = ['mountpoint']
+        self.t.undo_mounts('rootdir')
         self.t.logger.assert_has_calls([
             mock.call.debug('Unmounting runroot mounts'),
             mock.call.info("Unmounting (runroot): ['mountpoint', 'mount_2', 'mount_1']"),
@@ -302,11 +314,10 @@ class TestMounts(unittest.TestCase):
         os_unlink.reset_mock()
         getstatusoutput.return_value = (1, 'error')
         path_exists.return_value = True
-        with mock.patch('runroot.open', mock.mock_open(read_data = 'mountpoint')):
-            with self.assertRaises(koji.GenericError) as cm:
-                self.t.undo_mounts('rootdir')
-            self.assertEqual(cm.exception.message,
-                'Unable to unmount: mountpoint: error, mount_2: error, mount_1: error')
+        with self.assertRaises(koji.GenericError) as cm:
+            self.t.undo_mounts('rootdir')
+        self.assertEqual(cm.exception.args[0],
+            'Unable to unmount: mountpoint: error, mount_2: error, mount_1: error')
 
         os_unlink.assert_not_called()
 
diff --git a/tests/test_plugins/test_runroot_cli.py b/tests/test_plugins/test_runroot_cli.py
index c1e23fe..5d310b0 100644
--- a/tests/test_plugins/test_runroot_cli.py
+++ b/tests/test_plugins/test_runroot_cli.py
@@ -1,7 +1,10 @@
 from __future__ import absolute_import
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 from . import load_plugin
diff --git a/tests/test_plugins/test_runroot_hub.py b/tests/test_plugins/test_runroot_hub.py
index 79b5696..6c64f3c 100644
--- a/tests/test_plugins/test_runroot_hub.py
+++ b/tests/test_plugins/test_runroot_hub.py
@@ -1,5 +1,8 @@
-import unittest
 import mock
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import runroot_hub
diff --git a/tests/test_plugins/test_save_failed_tree_builder.py b/tests/test_plugins/test_save_failed_tree_builder.py
index 920f605..909e8a3 100644
--- a/tests/test_plugins/test_save_failed_tree_builder.py
+++ b/tests/test_plugins/test_save_failed_tree_builder.py
@@ -2,7 +2,10 @@ from __future__ import absolute_import
 import mock
 import os
 import sys
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 # alter pythonpath to not load hub plugin
 sys.path = [os.path.join(os.path.dirname(__file__), '../../plugins/builder')] + sys.path
diff --git a/tests/test_plugins/test_save_failed_tree_cli.py b/tests/test_plugins/test_save_failed_tree_cli.py
index 010bdbf..ec6fb7f 100644
--- a/tests/test_plugins/test_save_failed_tree_cli.py
+++ b/tests/test_plugins/test_save_failed_tree_cli.py
@@ -1,6 +1,9 @@
 import mock
 import six
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 
diff --git a/tests/test_scm.py b/tests/test_scm.py
index 43a8345..6eb3910 100644
--- a/tests/test_scm.py
+++ b/tests/test_scm.py
@@ -1,11 +1,11 @@
-import mock
-import unittest
-
 import logging
+import mock
 import shutil
 import tempfile
-
-from pprint import pprint
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 import koji
 import koji.daemon
diff --git a/tests/test_www/test_taskinfo.py b/tests/test_www/test_taskinfo.py
index 159f7a0..950bc0c 100644
--- a/tests/test_www/test_taskinfo.py
+++ b/tests/test_www/test_taskinfo.py
@@ -1,11 +1,15 @@
 from __future__ import absolute_import
 from __future__ import print_function
-import unittest
 import mock
 import koji
 import copy
 import datetime
 
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 from mock import call
 from .loadwebindex import webidx
 

From e1eb160d5f046aeea518f300d50c2fc32eb327d7 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Jun 07 2018 07:11:06 +0000
Subject: [PATCH 2/3] more unit test fixes


---

diff --git a/tests/test_hub/test_get_upload_path.py b/tests/test_hub/test_get_upload_path.py
index cb88aa4..9958f27 100644
--- a/tests/test_hub/test_get_upload_path.py
+++ b/tests/test_hub/test_get_upload_path.py
@@ -1,6 +1,7 @@
 import os
 import mock
 import shutil
+import tempfile
 try:
     import unittest2 as unittest
 except ImportError:
@@ -12,6 +13,13 @@ from koji import GenericError
 
 class TestGetUploadPath(unittest.TestCase):
 
+    def setUp(self):
+        self.topdir = tempfile.mkdtemp()
+        mock.patch('koji.pathinfo._topdir', new=self.topdir).start()
+
+    def tearDown(self):
+        shutil.rmtree(self.topdir)
+        mock.patch.stopall()
 
     def test_get_upload_path_invalid_filename(self):
         with self.assertRaises(GenericError):
@@ -30,14 +38,12 @@ class TestGetUploadPath(unittest.TestCase):
             kojihub.get_upload_path(reldir='tasks/1/should_be_number', name='error', create=True)
 
     @mock.patch('kojihub.context')
-    @mock.patch('koji.pathinfo.work')
     @mock.patch('kojihub.Host')
-    def test_get_upload_path_invalid_upload_dir_owner(self, host, work, context):
-        work.return_value = '/tmp'
+    def test_get_upload_path_invalid_upload_dir_owner(self, host, context):
         cursor = mock.MagicMock()
         context.cnx.cursor.return_value = cursor
         reldir = 'fake/1/1'
-        fullpath = '{0}/{1}'.format(work.return_value, reldir)
+        fullpath = '%s/work/%s' % (self.topdir, reldir)
         os.makedirs(fullpath)
 
         with open('{0}/.user'.format(fullpath), 'wb') as f:
@@ -46,12 +52,8 @@ class TestGetUploadPath(unittest.TestCase):
         with self.assertRaises(GenericError):
             kojihub.get_upload_path(reldir=reldir, name='error', create=True)
 
-        shutil.rmtree('/tmp/fake')
-
-    @mock.patch('koji.pathinfo.work')
     @mock.patch('kojihub.Host')
-    def test_get_upload_path_invalid_upload_no_dir_owner(self, host, work):
-        work.return_value = '/tmp'
+    def test_get_upload_path_invalid_upload_no_dir_owner(self, host):
         dir = kojihub.get_upload_path(reldir='tasks/1/1', name='error', create=False)
-        assert dir == '/tmp/tasks/1/1/error'
+        assert dir == '%s/work/tasks/1/1/error' % self.topdir
 

From 73f712971aa50ea1edcf8f35d20dfb45ec36f16d Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Jun 07 2018 07:11:06 +0000
Subject: [PATCH 3/3] avoid skipIf in import-comps unit test


causes problems with unittest2 in epel6

---

diff --git a/tests/test_cli/test_import_comps.py b/tests/test_cli/test_import_comps.py
index 07a809c..1f78b87 100644
--- a/tests/test_cli/test_import_comps.py
+++ b/tests/test_cli/test_import_comps.py
@@ -18,6 +18,8 @@ try:
 except ImportError:
     yumcomps = None
 
+from nose.plugins.skip import SkipTest
+
 import koji_cli.commands
 from koji_cli.commands import handle_import_comps, _import_comps,\
                               _import_comps_alt
@@ -221,9 +223,10 @@ class TestImportComps(unittest.TestCase):
         else:
             self.assertEqual(cm.exception.code, 2)
 
-    @unittest.skipIf(libcomps is None, "No libcomps")
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_import_comps_libcomps(self, stdout):
+        if libcomps is None:
+            raise SkipTest('no libcomps')
         comps_file = os.path.dirname(__file__) + '/data/comps-example.xml'
         stdout_file = os.path.dirname(
             __file__) + '/data/comps-example.libcomps.out'
@@ -236,9 +239,10 @@ class TestImportComps(unittest.TestCase):
             calls_file,
             stdout)
 
-    @unittest.skipIf(libcomps is None, "No libcomps")
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     def test_import_comps_sample_libcomps(self, stdout):
+        if libcomps is None:
+            raise SkipTest('no libcomps')
         comps_file = os.path.dirname(__file__) + '/data/comps-sample.xml'
         stdout_file = os.path.dirname(
             __file__) + '/data/comps-sample.libcomps.out'
@@ -251,11 +255,12 @@ class TestImportComps(unittest.TestCase):
             calls_file,
             stdout)
 
-    @unittest.skipIf(yumcomps is None, "No yum.comps")
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.libcomps', new=None)
     @mock.patch('koji_cli.commands.yumcomps', create=True, new=yumcomps)
     def test_import_comps_yumcomps(self, stdout):
+        if yumcomps is None:
+            raise SkipTest('no yum.comps')
         comps_file = os.path.dirname(__file__) + '/data/comps-example.xml'
         stdout_file = os.path.dirname(
             __file__) + '/data/comps-example.yumcomps.out'
@@ -268,11 +273,12 @@ class TestImportComps(unittest.TestCase):
             calls_file,
             stdout)
 
-    @unittest.skipIf(yumcomps is None, "No yum.comps")
     @mock.patch('sys.stdout', new_callable=six.StringIO)
     @mock.patch('koji_cli.commands.libcomps', new=None)
     @mock.patch('koji_cli.commands.yumcomps', create=True, new=yumcomps)
     def test_import_comps_sample_yumcomps(self, stdout):
+        if yumcomps is None:
+            raise SkipTest('no yum.comps')
         comps_file = os.path.dirname(__file__) + '/data/comps-sample.xml'
         stdout_file = os.path.dirname(
             __file__) + '/data/comps-sample.yumcomps.out'

