changeset 7118:4c46ebbcf814

tests: update _BackendTestMixin to py.test and convert tests using it from self.assert to plain py.test style asserts
author Branko Majic <branko@majic.rs>
date Sat, 10 Feb 2018 17:20:43 +0100
parents 5c9eb37bdec4
children 1d098adf3bf6
files kallithea/tests/vcs/base.py kallithea/tests/vcs/test_archives.py kallithea/tests/vcs/test_branches.py kallithea/tests/vcs/test_changesets.py kallithea/tests/vcs/test_filenodes_unicode_path.py kallithea/tests/vcs/test_getitem.py kallithea/tests/vcs/test_getslice.py kallithea/tests/vcs/test_git.py kallithea/tests/vcs/test_workdirs.py
diffstat 9 files changed, 262 insertions(+), 306 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/tests/vcs/base.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/base.py	Sat Feb 10 17:20:43 2018 +0100
@@ -8,7 +8,6 @@
 import datetime
 
 from kallithea.lib import vcs
-from kallithea.lib.vcs.utils.compat import unittest
 from kallithea.lib.vcs.nodes import FileNode
 
 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
@@ -62,7 +61,7 @@
         return commits
 
     @classmethod
-    def setUpClass(cls):
+    def setup_class(cls):
         Backend = cls.get_backend()
         cls.backend_class = Backend
         cls.repo_path = get_new_dir(str(time.time()))
@@ -83,16 +82,16 @@
                                      date=commit['date'])
 
     @classmethod
-    def tearDownClass(cls):
+    def teardown_class(cls):
         if not getattr(cls, 'recreate_repo_per_test', False) and \
             'VCS_REMOVE_TEST_DIRS' in os.environ:
             shutil.rmtree(cls.repo_path)
 
-    def setUp(self):
+    def setup_method(self, method):
         if getattr(self, 'recreate_repo_per_test', False):
-            self.__class__.setUpClass()
+            self.__class__.setup_class()
 
-    def tearDown(self):
+    def teardown_method(self, method):
         if getattr(self, 'recreate_repo_per_test', False) and \
             'VCS_REMOVE_TEST_DIRS' in os.environ:
             shutil.rmtree(self.repo_path)
@@ -104,5 +103,4 @@
         'backend_alias': alias,
     }
     cls_name = ''.join(('%s base backend test' % alias).title().split())
-    bases = (_BackendTestMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    globals()[cls_name] = type(cls_name, (_BackendTestMixin,), attrs)
--- a/kallithea/tests/vcs/test_archives.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_archives.py	Sat Feb 10 17:20:43 2018 +0100
@@ -5,7 +5,7 @@
 import tempfile
 import StringIO
 
-from kallithea.lib.vcs.utils.compat import unittest
+import pytest
 
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.nodes import FileNode
@@ -40,9 +40,7 @@
             node_path = '%d/file_%d.txt' % (x, x)
             decompressed = StringIO.StringIO()
             decompressed.write(out.read('repo/' + node_path))
-            self.assertEqual(
-                decompressed.getvalue(),
-                self.tip.get_node(node_path).content)
+            assert decompressed.getvalue() == self.tip.get_node(node_path).content
 
     def test_archive_tgz(self):
         path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tgz-')[1]
@@ -55,9 +53,7 @@
 
         for x in xrange(5):
             node_path = '%d/file_%d.txt' % (x, x)
-            self.assertEqual(
-                open(os.path.join(outdir, 'repo/' + node_path)).read(),
-                self.tip.get_node(node_path).content)
+            assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content
 
     def test_archive_tbz2(self):
         path = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_tbz2-')[1]
@@ -70,9 +66,7 @@
 
         for x in xrange(5):
             node_path = '%d/file_%d.txt' % (x, x)
-            self.assertEqual(
-                open(os.path.join(outdir, 'repo/' + node_path)).read(),
-                self.tip.get_node(node_path).content)
+            assert open(os.path.join(outdir, 'repo/' + node_path)).read() == self.tip.get_node(node_path).content
 
     def test_archive_default_stream(self):
         tmppath = tempfile.mkstemp(dir=TESTS_TMP_PATH, prefix='test_archive_default_stream-')[1]
@@ -87,19 +81,19 @@
             # the gzip header contains a MTIME header
             # because is takes a little bit of time from one fill_archive call to the next
             # this part may differ so don't include that part in the comparison
-            self.assertEqual(file_content[:4], stringio_content[:4])
-            self.assertEqual(file_content[8:], stringio_content[8:])
+            assert file_content[:4] == stringio_content[:4]
+            assert file_content[8:] == stringio_content[8:]
 
     def test_archive_wrong_kind(self):
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             self.tip.fill_archive(kind='wrong kind')
 
     def test_archive_empty_prefix(self):
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             self.tip.fill_archive(prefix='')
 
     def test_archive_prefix_with_leading_slash(self):
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             self.tip.fill_archive(prefix='/any')
 
 
@@ -108,6 +102,5 @@
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s archive test' % alias).title().split())
-    bases = (ArchivesTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = ''.join(('test %s archive' % alias).title().split())
+    globals()[cls_name] = type(cls_name, (ArchivesTestCaseMixin,), attrs)
--- a/kallithea/tests/vcs/test_branches.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_branches.py	Sat Feb 10 17:20:43 2018 +0100
@@ -1,6 +1,5 @@
 import datetime
 from kallithea.lib import vcs
-from kallithea.lib.vcs.utils.compat import unittest
 from kallithea.lib.vcs.nodes import FileNode
 
 from kallithea.tests.vcs.base import _BackendTestMixin
@@ -39,12 +38,12 @@
 
     def test_simple(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip.date, datetime.datetime(2010, 1, 1, 21))
+        assert tip.date == datetime.datetime(2010, 1, 1, 21)
 
     def test_new_branch(self):
         # This check must not be removed to ensure the 'branches' LazyProperty
         # gets hit *before* the new 'foobar' branch got created:
-        self.assertFalse('foobar' in self.repo.branches)
+        assert 'foobar' not in self.repo.branches
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         foobar_tip = self.imc.commit(
@@ -52,8 +51,8 @@
             author=u'joe',
             branch='foobar',
         )
-        self.assertTrue('foobar' in self.repo.branches)
-        self.assertEqual(foobar_tip.branch, 'foobar')
+        assert 'foobar' in self.repo.branches
+        assert foobar_tip.branch == 'foobar'
 
     def test_new_head(self):
         tip = self.repo.get_changeset()
@@ -81,14 +80,13 @@
             parents=[newtip, foobar_tip],
         )
 
-        self.assertEqual(newest_tip.branch,
-            self.backend_class.DEFAULT_BRANCH_NAME)
+        assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
 
     def test_branch_with_slash_in_name(self):
         self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
         self.imc.commit(u'Branch with a slash!', author=u'joe',
             branch='issue/123')
-        self.assertTrue('issue/123' in self.repo.branches)
+        assert 'issue/123' in self.repo.branches
 
     def test_branch_with_slash_in_name_and_similar_without(self):
         self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
@@ -97,8 +95,8 @@
         self.imc.add(vcs.nodes.FileNode('extrafile II', content='Some data\n'))
         self.imc.commit(u'Branch without a slash...', author=u'joe',
             branch='123')
-        self.assertIn('issue/123', self.repo.branches)
-        self.assertIn('123', self.repo.branches)
+        assert 'issue/123' in self.repo.branches
+        assert '123' in self.repo.branches
 
 
 # For each backend create test case class
@@ -106,6 +104,5 @@
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s branches test' % alias).title().split())
-    bases = (BranchesTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = ''.join(('test %s branches' % alias).title().split())
+    globals()[cls_name] = type(cls_name, (BranchesTestCaseMixin,), attrs)
--- a/kallithea/tests/vcs/test_changesets.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_changesets.py	Sat Feb 10 17:20:43 2018 +0100
@@ -3,7 +3,7 @@
 import time
 import datetime
 
-from kallithea.lib.vcs.utils.compat import unittest
+import pytest
 
 from kallithea.lib import vcs
 
@@ -21,7 +21,7 @@
 from kallithea.tests.vcs.conf import SCM_TESTS, get_new_dir
 
 
-class TestBaseChangeset(unittest.TestCase):
+class TestBaseChangeset(object):
 
     def test_as_dict(self):
         changeset = BaseChangeset()
@@ -35,7 +35,7 @@
         changeset.added = [FileNode('foo/bar/baz'), FileNode(u'foobar'), FileNode(u'blåbærgrød')]
         changeset.changed = []
         changeset.removed = []
-        self.assertEqual(changeset.as_dict(), {
+        assert changeset.as_dict() == {
             'id': 'ID',
             'raw_id': 'RAW_ID',
             'short_id': 'SHORT_ID',
@@ -49,7 +49,7 @@
             'added': ['foo/bar/baz', 'foobar', u'bl\xe5b\xe6rgr\xf8d'],
             'changed': [],
             'removed': [],
-        })
+        }
 
 
 class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin):
@@ -76,10 +76,11 @@
             author=u'joe',
             branch='foobar',
         )
-        self.assertTrue('foobar' in self.repo.branches)
-        self.assertEqual(foobar_tip.branch, 'foobar')
+        assert 'foobar' in self.repo.branches
+        assert foobar_tip.branch == 'foobar'
         # 'foobar' should be the only branch that contains the new commit
-        self.assertNotEqual(*self.repo.branches.values())
+        branches = self.repo.branches.values()
+        assert branches[0] != branches[1]
 
     def test_new_head_in_default_branch(self):
         tip = self.repo.get_changeset()
@@ -107,8 +108,7 @@
             parents=[newtip, foobar_tip],
         )
 
-        self.assertEqual(newest_tip.branch,
-            self.backend_class.DEFAULT_BRANCH_NAME)
+        assert newest_tip.branch == self.backend_class.DEFAULT_BRANCH_NAME
 
     def test_get_changesets_respects_branch_name(self):
         tip = self.repo.get_changeset()
@@ -127,25 +127,25 @@
         )
         default_branch_changesets = self.repo.get_changesets(
             branch_name=self.repo.DEFAULT_BRANCH_NAME)
-        self.assertNotIn(doc_changeset, default_branch_changesets)
+        assert doc_changeset not in default_branch_changesets
 
     def test_get_changeset_by_branch(self):
         for branch, sha in self.repo.branches.iteritems():
-            self.assertEqual(sha, self.repo.get_changeset(branch).raw_id)
+            assert sha == self.repo.get_changeset(branch).raw_id
 
     def test_get_changeset_by_tag(self):
         for tag, sha in self.repo.tags.iteritems():
-            self.assertEqual(sha, self.repo.get_changeset(tag).raw_id)
+            assert sha == self.repo.get_changeset(tag).raw_id
 
     def test_get_changeset_parents(self):
         for test_rev in [1, 2, 3]:
             sha = self.repo.get_changeset(test_rev-1)
-            self.assertEqual([sha], self.repo.get_changeset(test_rev).parents)
+            assert [sha] == self.repo.get_changeset(test_rev).parents
 
     def test_get_changeset_children(self):
         for test_rev in [1, 2, 3]:
             sha = self.repo.get_changeset(test_rev+1)
-            self.assertEqual([sha], self.repo.get_changeset(test_rev).children)
+            assert [sha] == self.repo.get_changeset(test_rev).children
 
 
 class _ChangesetsTestCaseMixin(_BackendTestMixin):
@@ -166,139 +166,140 @@
 
     def test_simple(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip.date, datetime.datetime(2010, 1, 3, 20))
+        assert tip.date == datetime.datetime(2010, 1, 3, 20)
 
     def test_get_changesets_is_ordered_by_date(self):
         changesets = list(self.repo.get_changesets())
         ordered_by_date = sorted(changesets,
             key=lambda cs: cs.date)
-        self.assertItemsEqual(changesets, ordered_by_date)
+
+        assert changesets == ordered_by_date
 
     def test_get_changesets_respects_start(self):
         second_id = self.repo.revisions[1]
         changesets = list(self.repo.get_changesets(start=second_id))
-        self.assertEqual(len(changesets), 4)
+        assert len(changesets) == 4
 
     def test_get_changesets_numerical_id_respects_start(self):
         second_id = 1
         changesets = list(self.repo.get_changesets(start=second_id))
-        self.assertEqual(len(changesets), 4)
+        assert len(changesets) == 4
 
     def test_get_changesets_includes_start_changeset(self):
         second_id = self.repo.revisions[1]
         changesets = list(self.repo.get_changesets(start=second_id))
-        self.assertEqual(changesets[0].raw_id, second_id)
+        assert changesets[0].raw_id == second_id
 
     def test_get_changesets_respects_end(self):
         second_id = self.repo.revisions[1]
         changesets = list(self.repo.get_changesets(end=second_id))
-        self.assertEqual(changesets[-1].raw_id, second_id)
-        self.assertEqual(len(changesets), 2)
+        assert changesets[-1].raw_id == second_id
+        assert len(changesets) == 2
 
     def test_get_changesets_numerical_id_respects_end(self):
         second_id = 1
         changesets = list(self.repo.get_changesets(end=second_id))
-        self.assertEqual(changesets.index(changesets[-1]), second_id)
-        self.assertEqual(len(changesets), 2)
+        assert changesets.index(changesets[-1]) == second_id
+        assert len(changesets) == 2
 
     def test_get_changesets_respects_both_start_and_end(self):
         second_id = self.repo.revisions[1]
         third_id = self.repo.revisions[2]
         changesets = list(self.repo.get_changesets(start=second_id,
             end=third_id))
-        self.assertEqual(len(changesets), 2)
+        assert len(changesets) == 2
 
     def test_get_changesets_numerical_id_respects_both_start_and_end(self):
         changesets = list(self.repo.get_changesets(start=2, end=3))
-        self.assertEqual(len(changesets), 2)
+        assert len(changesets) == 2
 
     def test_get_changesets_on_empty_repo_raises_EmptyRepository_error(self):
         Backend = self.get_backend()
         repo_path = get_new_dir(str(time.time()))
         repo = Backend(repo_path, create=True)
 
-        with self.assertRaises(EmptyRepositoryError):
+        with pytest.raises(EmptyRepositoryError):
             list(repo.get_changesets(start='foobar'))
 
     def test_get_changesets_includes_end_changeset(self):
         second_id = self.repo.revisions[1]
         changesets = list(self.repo.get_changesets(end=second_id))
-        self.assertEqual(changesets[-1].raw_id, second_id)
+        assert changesets[-1].raw_id == second_id
 
     def test_get_changesets_respects_start_date(self):
         start_date = datetime.datetime(2010, 2, 1)
         for cs in self.repo.get_changesets(start_date=start_date):
-            self.assertGreaterEqual(cs.date, start_date)
+            assert cs.date >= start_date
 
     def test_get_changesets_respects_end_date(self):
         start_date = datetime.datetime(2010, 1, 1)
         end_date = datetime.datetime(2010, 2, 1)
         for cs in self.repo.get_changesets(start_date=start_date,
                                            end_date=end_date):
-            self.assertGreaterEqual(cs.date, start_date)
-            self.assertLessEqual(cs.date, end_date)
+            assert cs.date >= start_date
+            assert cs.date <= end_date
 
     def test_get_changesets_respects_start_date_and_end_date(self):
         end_date = datetime.datetime(2010, 2, 1)
         for cs in self.repo.get_changesets(end_date=end_date):
-            self.assertLessEqual(cs.date, end_date)
+            assert cs.date <= end_date
 
     def test_get_changesets_respects_reverse(self):
         changesets_id_list = [cs.raw_id for cs in
             self.repo.get_changesets(reverse=True)]
-        self.assertItemsEqual(changesets_id_list, reversed(self.repo.revisions))
+        assert changesets_id_list == list(reversed(self.repo.revisions))
 
     def test_get_filenodes_generator(self):
         tip = self.repo.get_changeset()
         filepaths = [node.path for node in tip.get_filenodes_generator()]
-        self.assertItemsEqual(filepaths, ['file_%d.txt' % x for x in xrange(5)])
+        assert filepaths == ['file_%d.txt' % x for x in xrange(5)]
 
     def test_size(self):
         tip = self.repo.get_changeset()
         size = 5 * len('Foobar N') # Size of 5 files
-        self.assertEqual(tip.size, size)
+        assert tip.size == size
 
     def test_author(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip.author, u'Joe Doe <joe.doe@example.com>')
+        assert tip.author == u'Joe Doe <joe.doe@example.com>'
 
     def test_author_name(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip.author_name, u'Joe Doe')
+        assert tip.author_name == u'Joe Doe'
 
     def test_author_email(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip.author_email, u'joe.doe@example.com')
+        assert tip.author_email == u'joe.doe@example.com'
 
     def test_get_changesets_raise_changesetdoesnotexist_for_wrong_start(self):
-        with self.assertRaises(ChangesetDoesNotExistError):
+        with pytest.raises(ChangesetDoesNotExistError):
             list(self.repo.get_changesets(start='foobar'))
 
     def test_get_changesets_raise_changesetdoesnotexist_for_wrong_end(self):
-        with self.assertRaises(ChangesetDoesNotExistError):
+        with pytest.raises(ChangesetDoesNotExistError):
             list(self.repo.get_changesets(end='foobar'))
 
     def test_get_changesets_raise_branchdoesnotexist_for_wrong_branch_name(self):
-        with self.assertRaises(BranchDoesNotExistError):
+        with pytest.raises(BranchDoesNotExistError):
             list(self.repo.get_changesets(branch_name='foobar'))
 
     def test_get_changesets_raise_repositoryerror_for_wrong_start_end(self):
         start = self.repo.revisions[-1]
         end = self.repo.revisions[0]
-        with self.assertRaises(RepositoryError):
+        with pytest.raises(RepositoryError):
             list(self.repo.get_changesets(start=start, end=end))
 
     def test_get_changesets_numerical_id_reversed(self):
-        with self.assertRaises(RepositoryError):
+        with pytest.raises(RepositoryError):
             [x for x in self.repo.get_changesets(start=3, end=2)]
 
     def test_get_changesets_numerical_id_respects_both_start_and_end_last(self):
-        with self.assertRaises(RepositoryError):
+        with pytest.raises(RepositoryError):
             last = len(self.repo.revisions)
             list(self.repo.get_changesets(start=last-1, end=last-2))
 
     def test_get_changesets_numerical_id_last_zero_error(self):
-        with self.assertRaises(RepositoryError):
+        with pytest.raises(RepositoryError):
             last = len(self.repo.revisions)
             list(self.repo.get_changesets(start=last-1, end=0))
 
@@ -335,40 +336,40 @@
 
     def test_initial_commit(self):
         changeset = self.repo.get_changeset(0)
-        self.assertItemsEqual(changeset.added, [
+        assert sorted(list(changeset.added)) == sorted([
             changeset.get_node('foo/bar'),
             changeset.get_node('foo/bał'),
             changeset.get_node('foobar'),
             changeset.get_node('qwe'),
         ])
-        self.assertItemsEqual(changeset.changed, [])
-        self.assertItemsEqual(changeset.removed, [])
+        assert list(changeset.changed) == []
+        assert list(changeset.removed) == []
         assert u'foo/ba\u0142' in changeset.as_dict()['added']
         assert u'foo/ba\u0142' in changeset.__json__(with_file_list=True)['added']
 
     def test_head_added(self):
         changeset = self.repo.get_changeset()
-        self.assertTrue(isinstance(changeset.added, AddedFileNodesGenerator))
-        self.assertItemsEqual(changeset.added, [
+        assert isinstance(changeset.added, AddedFileNodesGenerator)
+        assert list(changeset.added) == [
             changeset.get_node('fallout'),
-        ])
-        self.assertTrue(isinstance(changeset.changed, ChangedFileNodesGenerator))
-        self.assertItemsEqual(changeset.changed, [
+        ]
+        assert isinstance(changeset.changed, ChangedFileNodesGenerator)
+        assert list(changeset.changed) == [
             changeset.get_node('foo/bar'),
             changeset.get_node('foobar'),
-        ])
-        self.assertTrue(isinstance(changeset.removed, RemovedFileNodesGenerator))
-        self.assertEqual(len(changeset.removed), 1)
-        self.assertEqual(list(changeset.removed)[0].path, 'qwe')
+        ]
+        assert isinstance(changeset.removed, RemovedFileNodesGenerator)
+        assert len(changeset.removed) == 1
+        assert list(changeset.removed)[0].path == 'qwe'
 
     def test_get_filemode(self):
         changeset = self.repo.get_changeset()
-        self.assertEqual(33188, changeset.get_file_mode('foo/bar'))
+        assert 33188 == changeset.get_file_mode('foo/bar')
 
     def test_get_filemode_non_ascii(self):
         changeset = self.repo.get_changeset()
-        self.assertEqual(33188, changeset.get_file_mode('foo/bał'))
-        self.assertEqual(33188, changeset.get_file_mode(u'foo/bał'))
+        assert 33188 == changeset.get_file_mode('foo/bał')
+        assert 33188 == changeset.get_file_mode(u'foo/bał')
 
 
 # For each backend create test case class
@@ -377,16 +378,13 @@
         'backend_alias': alias,
     }
     # tests with additional commits
-    cls_name = alias.title() + 'ChangesetsWithCommitsTest'
-    bases = (_ChangesetsWithCommitsTestCaseixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = 'Test' + alias.title() + 'ChangesetsWithCommits'
+    globals()[cls_name] = type(cls_name, (_ChangesetsWithCommitsTestCaseixin,), attrs)
 
     # tests without additional commits
-    cls_name = alias.title() + 'ChangesetsTest'
-    bases = (_ChangesetsTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = 'Test' + alias.title() + 'Changesets'
+    globals()[cls_name] = type(cls_name, (_ChangesetsTestCaseMixin,), attrs)
 
     # tests changes
-    cls_name = alias.title() + 'ChangesetsChangesTest'
-    bases = (_ChangesetsChangesTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = 'Test' + alias.title() + 'ChangesetsChanges'
+    globals()[cls_name] = type(cls_name, (_ChangesetsChangesTestCaseMixin,), attrs)
--- a/kallithea/tests/vcs/test_filenodes_unicode_path.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_filenodes_unicode_path.py	Sat Feb 10 17:20:43 2018 +0100
@@ -30,14 +30,14 @@
     def test_filenode_path(self):
         node = self.tip.get_node(self.fname)
         unode = self.tip.get_node(self.ufname)
-        self.assertEqual(node, unode)
+        assert node == unode
 
 
 for alias in SCM_TESTS:
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s file node unicode path test' % alias).title()
+    cls_name = ''.join(('test %s file node unicode path' % alias).title()
         .split())
     bases = (FileNodeUnicodePathTestsMixin, BackendBaseTestCase)
     globals()[cls_name] = type(cls_name, bases, attrs)
--- a/kallithea/tests/vcs/test_getitem.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_getitem.py	Sat Feb 10 17:20:43 2018 +0100
@@ -3,7 +3,6 @@
 from kallithea.tests.vcs.base import _BackendTestMixin
 from kallithea.tests.vcs.conf import SCM_TESTS
 from kallithea.lib.vcs.nodes import FileNode
-from kallithea.lib.vcs.utils.compat import unittest
 
 
 class GetitemTestCaseMixin(_BackendTestMixin):
@@ -22,11 +21,11 @@
             }
 
     def test__getitem__last_item_is_tip(self):
-        self.assertEqual(self.repo[-1], self.repo.get_changeset())
+        assert self.repo[-1] == self.repo.get_changeset()
 
     def test__getitem__returns_correct_items(self):
         changesets = [self.repo[x] for x in xrange(len(self.repo.revisions))]
-        self.assertEqual(changesets, list(self.repo.get_changesets()))
+        assert changesets == list(self.repo.get_changesets())
 
 
 # For each backend create test case class
@@ -34,6 +33,5 @@
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s getitem test' % alias).title().split())
-    bases = (GetitemTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = ''.join(('test %s getitem' % alias).title().split())
+    globals()[cls_name] = type(cls_name, (GetitemTestCaseMixin,), attrs)
--- a/kallithea/tests/vcs/test_getslice.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_getslice.py	Sat Feb 10 17:20:43 2018 +0100
@@ -2,8 +2,6 @@
 
 from kallithea.lib.vcs.nodes import FileNode
 
-from kallithea.lib.vcs.utils.compat import unittest
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 from kallithea.tests.vcs.conf import SCM_TESTS
 
@@ -24,23 +22,19 @@
             }
 
     def test__getslice__last_item_is_tip(self):
-        self.assertEqual(list(self.repo[-1:])[0], self.repo.get_changeset())
+        assert list(self.repo[-1:])[0] == self.repo.get_changeset()
 
     def test__getslice__respects_start_index(self):
-        self.assertEqual(list(self.repo[2:]),
-            [self.repo.get_changeset(rev) for rev in self.repo.revisions[2:]])
+        assert list(self.repo[2:]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[2:]]
 
     def test__getslice__respects_negative_start_index(self):
-        self.assertEqual(list(self.repo[-2:]),
-            [self.repo.get_changeset(rev) for rev in self.repo.revisions[-2:]])
+        assert list(self.repo[-2:]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[-2:]]
 
     def test__getslice__respects_end_index(self):
-        self.assertEqual(list(self.repo[:2]),
-            [self.repo.get_changeset(rev) for rev in self.repo.revisions[:2]])
+        assert list(self.repo[:2]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[:2]]
 
     def test__getslice__respects_negative_end_index(self):
-        self.assertEqual(list(self.repo[:-2]),
-            [self.repo.get_changeset(rev) for rev in self.repo.revisions[:-2]])
+        assert list(self.repo[:-2]) == [self.repo.get_changeset(rev) for rev in self.repo.revisions[:-2]]
 
 
 # For each backend create test case class
@@ -48,6 +42,5 @@
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s getslice test' % alias).title().split())
-    bases = (GetsliceTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = ''.join(('test %s getslice' % alias).title().split())
+    globals()[cls_name] = type(cls_name, (GetsliceTestCaseMixin,), attrs)
--- a/kallithea/tests/vcs/test_git.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_git.py	Sat Feb 10 17:20:43 2018 +0100
@@ -9,14 +9,13 @@
 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
-from kallithea.lib.vcs.utils.compat import unittest
 from kallithea.model.scm import ScmModel
 
 from kallithea.tests.vcs.base import _BackendTestMixin
 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir
 
 
-class GitRepositoryTest(unittest.TestCase):
+class TestGitRepository(object):
 
     def __check_for_existing_repo(self):
         if os.path.exists(TEST_GIT_REPO_CLONE):
@@ -24,20 +23,21 @@
                       'exists. You should manually remove it first.'
                       % TEST_GIT_REPO_CLONE)
 
-    def setUp(self):
+    def setup_method(self):
         self.repo = GitRepository(TEST_GIT_REPO)
 
     def test_wrong_repo_path(self):
         wrong_repo_path = os.path.join(TESTS_TMP_PATH, 'errorrepo')
-        self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
+        with pytest.raises(RepositoryError):
+            GitRepository(wrong_repo_path)
 
     def test_git_cmd_injection(self):
         repo_inject_path = TEST_GIT_REPO + '; echo "Cake";'
-        with self.assertRaises(urllib2.URLError):
+        with pytest.raises(urllib2.URLError):
             # Should fail because URL will contain the parts after ; too
             GitRepository(get_new_dir('injection-repo'), src_url=repo_inject_path, update_after_clone=True, create=True)
 
-        with self.assertRaises(RepositoryError):
+        with pytest.raises(RepositoryError):
             # Should fail on direct clone call, which as of this writing does not happen outside of class
             clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
             clone_fail_repo.clone(repo_inject_path, update_after_clone=True,)
@@ -51,7 +51,7 @@
             tricky_path = get_new_dir("tricky-path-repo-$'\"`")
         successfully_cloned = GitRepository(tricky_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
         # Repo should have been created
-        self.assertFalse(successfully_cloned._repo.bare)
+        assert not successfully_cloned._repo.bare
 
         if sys.platform == 'win32':
             # windows does not allow '"' in dir names
@@ -61,7 +61,7 @@
             tricky_path_2 = get_new_dir("tricky-path-2-repo-$'\"`")
         successfully_cloned2 = GitRepository(tricky_path_2, src_url=tricky_path, bare=True, create=True)
         # Repo should have been created and thus used correct quoting for clone
-        self.assertTrue(successfully_cloned2._repo.bare)
+        assert successfully_cloned2._repo.bare
 
         # Should pass because URL has been properly quoted
         successfully_cloned.pull(tricky_path_2)
@@ -71,73 +71,69 @@
         repo_path = get_new_dir("path with spaces")
         repo = GitRepository(repo_path, src_url=None, bare=True, create=True)
         # Repo should have been created
-        self.assertTrue(repo._repo.bare)
+        assert repo._repo.bare
 
     def test_repo_clone(self):
         self.__check_for_existing_repo()
         repo = GitRepository(TEST_GIT_REPO)
         repo_clone = GitRepository(TEST_GIT_REPO_CLONE,
             src_url=TEST_GIT_REPO, create=True, update_after_clone=True)
-        self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
+        assert len(repo.revisions) == len(repo_clone.revisions)
         # Checking hashes of changesets should be enough
         for changeset in repo.get_changesets():
             raw_id = changeset.raw_id
-            self.assertEqual(raw_id, repo_clone.get_changeset(raw_id).raw_id)
+            assert raw_id == repo_clone.get_changeset(raw_id).raw_id
 
     def test_repo_clone_with_spaces_in_path(self):
         repo_path = get_new_dir("path with spaces")
         successfully_cloned = GitRepository(repo_path, src_url=TEST_GIT_REPO, update_after_clone=True, create=True)
         # Repo should have been created
-        self.assertFalse(successfully_cloned._repo.bare)
+        assert not successfully_cloned._repo.bare
 
         successfully_cloned.pull(TEST_GIT_REPO)
         self.repo.fetch(repo_path)
 
     def test_repo_clone_without_create(self):
-        self.assertRaises(RepositoryError, GitRepository,
-            TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
+        with pytest.raises(RepositoryError):
+            GitRepository(TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
 
     def test_repo_clone_with_update(self):
         repo = GitRepository(TEST_GIT_REPO)
         clone_path = TEST_GIT_REPO_CLONE + '_with_update'
         repo_clone = GitRepository(clone_path,
             create=True, src_url=TEST_GIT_REPO, update_after_clone=True)
-        self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
+        assert len(repo.revisions) == len(repo_clone.revisions)
 
         # check if current workdir was updated
         fpath = os.path.join(clone_path, 'MANIFEST.in')
-        self.assertEqual(True, os.path.isfile(fpath),
-            'Repo was cloned and updated but file %s could not be found'
-            % fpath)
+        assert os.path.isfile(fpath) == True, 'Repo was cloned and updated but file %s could not be found' % fpath
 
     def test_repo_clone_without_update(self):
         repo = GitRepository(TEST_GIT_REPO)
         clone_path = TEST_GIT_REPO_CLONE + '_without_update'
         repo_clone = GitRepository(clone_path,
             create=True, src_url=TEST_GIT_REPO, update_after_clone=False)
-        self.assertEqual(len(repo.revisions), len(repo_clone.revisions))
+        assert len(repo.revisions) == len(repo_clone.revisions)
         # check if current workdir was *NOT* updated
         fpath = os.path.join(clone_path, 'MANIFEST.in')
         # Make sure it's not bare repo
-        self.assertFalse(repo_clone._repo.bare)
-        self.assertEqual(False, os.path.isfile(fpath),
-            'Repo was cloned and updated but file %s was found'
-            % fpath)
+        assert not repo_clone._repo.bare
+        assert os.path.isfile(fpath) == False, 'Repo was cloned and updated but file %s was found' % fpath
 
     def test_repo_clone_into_bare_repo(self):
         repo = GitRepository(TEST_GIT_REPO)
         clone_path = TEST_GIT_REPO_CLONE + '_bare.git'
         repo_clone = GitRepository(clone_path, create=True,
             src_url=repo.path, bare=True)
-        self.assertTrue(repo_clone._repo.bare)
+        assert repo_clone._repo.bare
 
     def test_create_repo_is_not_bare_by_default(self):
         repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
-        self.assertFalse(repo._repo.bare)
+        assert not repo._repo.bare
 
     def test_create_bare_repo(self):
         repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
-        self.assertTrue(repo._repo.bare)
+        assert repo._repo.bare
 
     def test_revisions(self):
         # there are 112 revisions (by now)
@@ -168,70 +164,68 @@
             '27d48942240f5b91dfda77accd2caac94708cc7d',
             '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
             'e686b958768ee96af8029fe19c6050b1a8dd3b2b'])
-        self.assertTrue(subset.issubset(set(self.repo.revisions)))
+        assert subset.issubset(set(self.repo.revisions))
 
     def test_slicing(self):
         # 4 1 5 10 95
         for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
                                  (10, 20, 10), (5, 100, 95)]:
             revs = list(self.repo[sfrom:sto])
-            self.assertEqual(len(revs), size)
-            self.assertEqual(revs[0], self.repo.get_changeset(sfrom))
-            self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1))
+            assert len(revs) == size
+            assert revs[0] == self.repo.get_changeset(sfrom)
+            assert revs[-1] == self.repo.get_changeset(sto - 1)
 
     def test_branches(self):
         # TODO: Need more tests here
         # Removed (those are 'remotes' branches for cloned repo)
-        #self.assertTrue('master' in self.repo.branches)
-        #self.assertTrue('gittree' in self.repo.branches)
-        #self.assertTrue('web-branch' in self.repo.branches)
+        #assert 'master' in self.repo.branches
+        #assert 'gittree' in self.repo.branches
+        #assert 'web-branch' in self.repo.branches
         for name, id in self.repo.branches.items():
-            self.assertTrue(isinstance(
-                self.repo.get_changeset(id), GitChangeset))
+            assert isinstance(self.repo.get_changeset(id), GitChangeset)
 
     def test_tags(self):
         # TODO: Need more tests here
-        self.assertTrue('v0.1.1' in self.repo.tags)
-        self.assertTrue('v0.1.2' in self.repo.tags)
+        assert 'v0.1.1' in self.repo.tags
+        assert 'v0.1.2' in self.repo.tags
         for name, id in self.repo.tags.items():
-            self.assertTrue(isinstance(
-                self.repo.get_changeset(id), GitChangeset))
+            assert isinstance(self.repo.get_changeset(id), GitChangeset)
 
     def _test_single_changeset_cache(self, revision):
         chset = self.repo.get_changeset(revision)
-        self.assertTrue(revision in self.repo.changesets)
-        self.assertTrue(chset is self.repo.changesets[revision])
+        assert revision in self.repo.changesets
+        assert chset is self.repo.changesets[revision]
 
     def test_initial_changeset(self):
         id = self.repo.revisions[0]
         init_chset = self.repo.get_changeset(id)
-        self.assertEqual(init_chset.message, 'initial import\n')
-        self.assertEqual(init_chset.author,
-            'Marcin Kuzminski <marcin@python-blog.com>')
+        assert init_chset.message == 'initial import\n'
+        assert init_chset.author == 'Marcin Kuzminski <marcin@python-blog.com>'
         for path in ('vcs/__init__.py',
                      'vcs/backends/BaseRepository.py',
                      'vcs/backends/__init__.py'):
-            self.assertTrue(isinstance(init_chset.get_node(path), FileNode))
+            assert isinstance(init_chset.get_node(path), FileNode)
         for path in ('', 'vcs', 'vcs/backends'):
-            self.assertTrue(isinstance(init_chset.get_node(path), DirNode))
+            assert isinstance(init_chset.get_node(path), DirNode)
 
-        self.assertRaises(NodeDoesNotExistError, init_chset.get_node, path='foobar')
+        with pytest.raises(NodeDoesNotExistError):
+            init_chset.get_node(path='foobar')
 
         node = init_chset.get_node('vcs/')
-        self.assertTrue(hasattr(node, 'kind'))
-        self.assertEqual(node.kind, NodeKind.DIR)
+        assert hasattr(node, 'kind')
+        assert node.kind == NodeKind.DIR
 
         node = init_chset.get_node('vcs')
-        self.assertTrue(hasattr(node, 'kind'))
-        self.assertEqual(node.kind, NodeKind.DIR)
+        assert hasattr(node, 'kind')
+        assert node.kind == NodeKind.DIR
 
         node = init_chset.get_node('vcs/__init__.py')
-        self.assertTrue(hasattr(node, 'kind'))
-        self.assertEqual(node.kind, NodeKind.FILE)
+        assert hasattr(node, 'kind')
+        assert node.kind == NodeKind.FILE
 
     def test_not_existing_changeset(self):
-        self.assertRaises(RepositoryError, self.repo.get_changeset,
-            'f' * 40)
+        with pytest.raises(RepositoryError):
+            self.repo.get_changeset('f' * 40)
 
     def test_changeset10(self):
 
@@ -249,23 +243,23 @@
 
 """
         node = chset10.get_node('README.rst')
-        self.assertEqual(node.kind, NodeKind.FILE)
-        self.assertEqual(node.content, readme)
+        assert node.kind == NodeKind.FILE
+        assert node.content == readme
 
 
-class GitChangesetTest(unittest.TestCase):
+class TestGitChangeset(object):
 
-    def setUp(self):
+    def setup_method(self):
         self.repo = GitRepository(TEST_GIT_REPO)
 
     def test_default_changeset(self):
         tip = self.repo.get_changeset()
-        self.assertEqual(tip, self.repo.get_changeset(None))
-        self.assertEqual(tip, self.repo.get_changeset('tip'))
+        assert tip == self.repo.get_changeset(None)
+        assert tip == self.repo.get_changeset('tip')
 
     def test_root_node(self):
         tip = self.repo.get_changeset()
-        self.assertTrue(tip.root is tip.get_node(''))
+        assert tip.root is tip.get_node('')
 
     def test_lazy_fetch(self):
         """
@@ -274,59 +268,59 @@
         is a key here. Written by running command after command in a shell.
         """
         commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
-        self.assertTrue(commit_id in self.repo.revisions)
+        assert commit_id in self.repo.revisions
         chset = self.repo.get_changeset(commit_id)
-        self.assertTrue(len(chset.nodes) == 0)
+        assert len(chset.nodes) == 0
         root = chset.root
-        self.assertTrue(len(chset.nodes) == 1)
-        self.assertTrue(len(root.nodes) == 8)
+        assert len(chset.nodes) == 1
+        assert len(root.nodes) == 8
         # accessing root.nodes updates chset.nodes
-        self.assertTrue(len(chset.nodes) == 9)
+        assert len(chset.nodes) == 9
 
         docs = root.get_node('docs')
         # we haven't yet accessed anything new as docs dir was already cached
-        self.assertTrue(len(chset.nodes) == 9)
-        self.assertTrue(len(docs.nodes) == 8)
+        assert len(chset.nodes) == 9
+        assert len(docs.nodes) == 8
         # accessing docs.nodes updates chset.nodes
-        self.assertTrue(len(chset.nodes) == 17)
+        assert len(chset.nodes) == 17
 
-        self.assertTrue(docs is chset.get_node('docs'))
-        self.assertTrue(docs is root.nodes[0])
-        self.assertTrue(docs is root.dirs[0])
-        self.assertTrue(docs is chset.get_node('docs'))
+        assert docs is chset.get_node('docs')
+        assert docs is root.nodes[0]
+        assert docs is root.dirs[0]
+        assert docs is chset.get_node('docs')
 
     def test_nodes_with_changeset(self):
         commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
         chset = self.repo.get_changeset(commit_id)
         root = chset.root
         docs = root.get_node('docs')
-        self.assertTrue(docs is chset.get_node('docs'))
+        assert docs is chset.get_node('docs')
         api = docs.get_node('api')
-        self.assertTrue(api is chset.get_node('docs/api'))
+        assert api is chset.get_node('docs/api')
         index = api.get_node('index.rst')
-        self.assertTrue(index is chset.get_node('docs/api/index.rst'))
-        self.assertTrue(index is chset.get_node('docs') \
-            .get_node('api') \
-            .get_node('index.rst'))
+        assert index is chset.get_node('docs/api/index.rst')
+        assert index is chset.get_node('docs') \
+                             .get_node('api') \
+                             .get_node('index.rst')
 
     def test_branch_and_tags(self):
         """
         rev0 = self.repo.revisions[0]
         chset0 = self.repo.get_changeset(rev0)
-        self.assertEqual(chset0.branch, 'master')
-        self.assertEqual(chset0.tags, [])
+        assert chset0.branch == 'master'
+        assert chset0.tags == []
 
         rev10 = self.repo.revisions[10]
         chset10 = self.repo.get_changeset(rev10)
-        self.assertEqual(chset10.branch, 'master')
-        self.assertEqual(chset10.tags, [])
+        assert chset10.branch == 'master'
+        assert chset10.tags == []
 
         rev44 = self.repo.revisions[44]
         chset44 = self.repo.get_changeset(rev44)
-        self.assertEqual(chset44.branch, 'web-branch')
+        assert chset44.branch == 'web-branch'
 
         tip = self.repo.get_changeset('tip')
-        self.assertTrue('tip' in tip.tags)
+        assert 'tip' in tip.tags
         """
         # Those tests would fail - branches are now going
         # to be changed at main API in order to support git backend
@@ -344,7 +338,7 @@
                 pytest.fail("Exceeded limit already (getting revision %s, "
                     "there are %s total revisions, offset=%s, limit=%s)"
                     % (rev_id, count, offset, limit))
-            self.assertEqual(changeset, self.repo.get_changeset(rev_id))
+            assert changeset == self.repo.get_changeset(rev_id)
         result = list(self.repo.get_changesets(limit=limit, offset=offset))
         start = offset
         end = limit and offset + limit or None
@@ -356,8 +350,8 @@
 
     def _test_file_size(self, revision, path, size):
         node = self.repo.get_changeset(revision).get_node(path)
-        self.assertTrue(node.is_file())
-        self.assertEqual(node.size, size)
+        assert node.is_file()
+        assert node.size == size
 
     def test_file_size(self):
         to_check = (
@@ -379,7 +373,7 @@
 
     def _test_dir_size(self, revision, path, size):
         node = self.repo.get_changeset(revision).get_node(path)
-        self.assertEqual(node.size, size)
+        assert node.size == size
 
     def test_dir_size(self):
         to_check = (
@@ -391,7 +385,7 @@
             self._test_dir_size(revision, path, size)
 
     def test_repo_size(self):
-        self.assertEqual(self.repo.size, 674076)
+        assert self.repo.size == 674076
 
     def test_file_history(self):
         # we can only check if those revisions are present in the history
@@ -455,10 +449,9 @@
         for path, revs in files.items():
             node = self.repo.get_changeset(revs[0]).get_node(path)
             node_revs = [chset.raw_id for chset in node.history]
-            self.assertTrue(set(revs).issubset(set(node_revs)),
-                "We assumed that %s is subset of revisions for which file %s "
-                "has been changed, and history of that node returned: %s"
-                % (revs, path, node_revs))
+            assert set(revs).issubset(set(node_revs)), "We assumed that %s is subset of revisions for which file %s " \
+                "has been changed, and history of that node returned: %s" \
+                % (revs, path, node_revs)
 
     def test_file_annotate(self):
         files = {
@@ -541,12 +534,12 @@
 
                 l1_1 = [x[1] for x in cs.get_file_annotate(fname)]
                 l1_2 = [x[2]().raw_id for x in cs.get_file_annotate(fname)]
-                self.assertEqual(l1_1, l1_2)
+                assert l1_1 == l1_2
                 l1 = l1_1
                 l2 = files[fname][rev]['changesets']
-                self.assertTrue(l1 == l2, "The lists of revision for %s@rev %s"
-                                "from annotation list should match each other, "
-                                "got \n%s \nvs \n%s " % (fname, rev, l1, l2))
+                assert l1 == l2, "The lists of revision for %s@rev %s" \
+                    "from annotation list should match each other, " \
+                    "got \n%s \nvs \n%s " % (fname, rev, l1, l2)
 
     def test_files_state(self):
         """
@@ -555,113 +548,103 @@
         node = self.repo \
             .get_changeset('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0') \
             .get_node('vcs/utils/diffs.py')
-        self.assertTrue(node.state, NodeState.ADDED)
-        self.assertTrue(node.added)
-        self.assertFalse(node.changed)
-        self.assertFalse(node.not_changed)
-        self.assertFalse(node.removed)
+        assert node.state, NodeState.ADDED
+        assert node.added
+        assert not node.changed
+        assert not node.not_changed
+        assert not node.removed
 
         node = self.repo \
             .get_changeset('33fa3223355104431402a888fa77a4e9956feb3e') \
             .get_node('.hgignore')
-        self.assertTrue(node.state, NodeState.CHANGED)
-        self.assertFalse(node.added)
-        self.assertTrue(node.changed)
-        self.assertFalse(node.not_changed)
-        self.assertFalse(node.removed)
+        assert node.state, NodeState.CHANGED
+        assert not node.added
+        assert node.changed
+        assert not node.not_changed
+        assert not node.removed
 
         node = self.repo \
             .get_changeset('e29b67bd158580fc90fc5e9111240b90e6e86064') \
             .get_node('setup.py')
-        self.assertTrue(node.state, NodeState.NOT_CHANGED)
-        self.assertFalse(node.added)
-        self.assertFalse(node.changed)
-        self.assertTrue(node.not_changed)
-        self.assertFalse(node.removed)
+        assert node.state, NodeState.NOT_CHANGED
+        assert not node.added
+        assert not node.changed
+        assert node.not_changed
+        assert not node.removed
 
         # If node has REMOVED state then trying to fetch it would raise
         # ChangesetError exception
         chset = self.repo.get_changeset(
             'fa6600f6848800641328adbf7811fd2372c02ab2')
         path = 'vcs/backends/BaseRepository.py'
-        self.assertRaises(NodeDoesNotExistError, chset.get_node, path)
+        with pytest.raises(NodeDoesNotExistError):
+            chset.get_node(path)
         # but it would be one of ``removed`` (changeset's attribute)
-        self.assertTrue(path in [rf.path for rf in chset.removed])
+        assert path in [rf.path for rf in chset.removed]
 
         chset = self.repo.get_changeset(
             '54386793436c938cff89326944d4c2702340037d')
         changed = ['setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
             'vcs/nodes.py']
-        self.assertEqual(set(changed), set([f.path for f in chset.changed]))
+        assert set(changed) == set([f.path for f in chset.changed])
 
     def test_commit_message_is_unicode(self):
         for cs in self.repo:
-            self.assertEqual(type(cs.message), unicode)
+            assert type(cs.message) == unicode
 
     def test_changeset_author_is_unicode(self):
         for cs in self.repo:
-            self.assertEqual(type(cs.author), unicode)
+            assert type(cs.author) == unicode
 
     def test_repo_files_content_is_unicode(self):
         changeset = self.repo.get_changeset()
         for node in changeset.get_node('/'):
             if node.is_file():
-                self.assertEqual(type(node.content), unicode)
+                assert type(node.content) == unicode
 
     def test_wrong_path(self):
         # There is 'setup.py' in the root dir but not there:
         path = 'foo/bar/setup.py'
         tip = self.repo.get_changeset()
-        self.assertRaises(VCSError, tip.get_node, path)
+        with pytest.raises(VCSError):
+            tip.get_node(path)
 
     def test_author_email(self):
-        self.assertEqual('marcin@python-blog.com',
-          self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3') \
-          .author_email)
-        self.assertEqual('lukasz.balcerzak@python-center.pl',
-          self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b') \
-          .author_email)
-        self.assertEqual('',
-          self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992') \
-          .author_email)
+        assert 'marcin@python-blog.com' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_email
+        assert 'lukasz.balcerzak@python-center.pl' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_email
+        assert '' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_email
 
     def test_author_username(self):
-        self.assertEqual('Marcin Kuzminski',
-          self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3') \
-          .author_name)
-        self.assertEqual('Lukasz Balcerzak',
-          self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b') \
-          .author_name)
-        self.assertEqual('marcink none@none',
-          self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992') \
-          .author_name)
+        assert 'Marcin Kuzminski' == self.repo.get_changeset('c1214f7e79e02fc37156ff215cd71275450cffc3').author_name
+        assert 'Lukasz Balcerzak' == self.repo.get_changeset('ff7ca51e58c505fec0dd2491de52c622bb7a806b').author_name
+        assert 'marcink none@none' == self.repo.get_changeset('8430a588b43b5d6da365400117c89400326e7992').author_name
 
 
-class GitSpecificTest(unittest.TestCase):
+class TestGitSpecific():
 
     def test_error_is_raised_for_added_if_diff_name_status_is_wrong(self):
         repo = mock.MagicMock()
         changeset = GitChangeset(repo, 'foobar')
         changeset._diff_name_status = 'foobar'
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             changeset.added
 
     def test_error_is_raised_for_changed_if_diff_name_status_is_wrong(self):
         repo = mock.MagicMock()
         changeset = GitChangeset(repo, 'foobar')
         changeset._diff_name_status = 'foobar'
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             changeset.added
 
     def test_error_is_raised_for_removed_if_diff_name_status_is_wrong(self):
         repo = mock.MagicMock()
         changeset = GitChangeset(repo, 'foobar')
         changeset._diff_name_status = 'foobar'
-        with self.assertRaises(VCSError):
+        with pytest.raises(VCSError):
             changeset.added
 
 
-class GitSpecificWithRepoTest(_BackendTestMixin, unittest.TestCase):
+class TestGitSpecificWithRepo(_BackendTestMixin):
     backend_alias = 'git'
 
     @classmethod
@@ -690,22 +673,20 @@
 
     def test_paths_slow_traversing(self):
         cs = self.repo.get_changeset()
-        self.assertEqual(cs.get_node('foobar').get_node('static').get_node('js')
-            .get_node('admin').get_node('base.js').content, 'base')
+        assert cs.get_node('foobar').get_node('static').get_node('js').get_node('admin').get_node('base.js').content == 'base'
 
     def test_paths_fast_traversing(self):
         cs = self.repo.get_changeset()
-        self.assertEqual(cs.get_node('foobar/static/js/admin/base.js').content,
-            'base')
+        assert cs.get_node('foobar/static/js/admin/base.js').content == 'base'
 
     def test_workdir_get_branch(self):
         self.repo.run_git_command(['checkout', '-b', 'production'])
         # Regression test: one of following would fail if we don't check
         # .git/HEAD file
         self.repo.run_git_command(['checkout', 'production'])
-        self.assertEqual(self.repo.workdir.get_branch(), 'production')
+        assert self.repo.workdir.get_branch() == 'production'
         self.repo.run_git_command(['checkout', 'master'])
-        self.assertEqual(self.repo.workdir.get_branch(), 'master')
+        assert self.repo.workdir.get_branch() == 'master'
 
     def test_get_diff_runs_git_command_with_hashes(self):
         self.repo.run_git_command = mock.Mock(return_value=['', ''])
@@ -729,7 +710,7 @@
              self.repo._get_revision(0), self.repo._get_revision(1), '--', 'foo'])
 
 
-class GitRegressionTest(_BackendTestMixin, unittest.TestCase):
+class TestGitRegression(_BackendTestMixin):
     backend_alias = 'git'
 
     @classmethod
@@ -763,21 +744,21 @@
     def test_similar_paths(self):
         cs = self.repo.get_changeset()
         paths = lambda *n: [x.path for x in n]
-        self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py'])
-        self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates'])
-        self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates'])
+        assert paths(*cs.get_nodes('bot')) == ['bot/build', 'bot/templates', 'bot/__init__.py']
+        assert paths(*cs.get_nodes('bot/build')) == ['bot/build/migrations', 'bot/build/static', 'bot/build/templates']
+        assert paths(*cs.get_nodes('bot/build/static')) == ['bot/build/static/templates']
         # this get_nodes below causes troubles !
-        self.assertEqual(paths(*cs.get_nodes('bot/build/static/templates')), ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html'])
-        self.assertEqual(paths(*cs.get_nodes('bot/build/templates')), ['bot/build/templates/err.html', 'bot/build/templates/err2.html'])
-        self.assertEqual(paths(*cs.get_nodes('bot/templates/')), ['bot/templates/404.html', 'bot/templates/500.html'])
+        assert paths(*cs.get_nodes('bot/build/static/templates')) == ['bot/build/static/templates/f.html', 'bot/build/static/templates/f1.html']
+        assert paths(*cs.get_nodes('bot/build/templates')) == ['bot/build/templates/err.html', 'bot/build/templates/err2.html']
+        assert paths(*cs.get_nodes('bot/templates/')) == ['bot/templates/404.html', 'bot/templates/500.html']
 
 
-class GitHooksTest(unittest.TestCase):
+class TestGitHooks(object):
     """
     Tests related to hook functionality of Git repositories.
     """
 
-    def setUp(self):
+    def setup_method(self):
         # For each run we want a fresh repo.
         self.repo_directory = get_new_dir("githookrepo")
         self.repo = GitRepository(self.repo_directory, create=True)
@@ -799,7 +780,7 @@
         ScmModel().install_git_hooks(repo=self.repo)
 
         for hook, hook_path in self.kallithea_hooks.iteritems():
-            self.assertTrue(os.path.exists(hook_path))
+            assert os.path.exists(hook_path)
 
     def test_kallithea_hooks_updated(self):
         """
@@ -814,7 +795,7 @@
 
         for hook, hook_path in self.kallithea_hooks.iteritems():
             with open(hook_path) as f:
-                self.assertNotIn("JUST_BOGUS", f.read())
+                assert "JUST_BOGUS" not in f.read()
 
     def test_custom_hooks_untouched(self):
         """
@@ -829,7 +810,7 @@
 
         for hook, hook_path in self.kallithea_hooks.iteritems():
             with open(hook_path) as f:
-                self.assertIn("CUSTOM_HOOK", f.read())
+                assert "CUSTOM_HOOK" in f.read()
 
     def test_custom_hooks_forced_update(self):
         """
@@ -844,4 +825,4 @@
 
         for hook, hook_path in self.kallithea_hooks.iteritems():
             with open(hook_path) as f:
-                self.assertIn("KALLITHEA_HOOK_VER", f.read())
+                assert "KALLITHEA_HOOK_VER" in f.read()
--- a/kallithea/tests/vcs/test_workdirs.py	Sat Feb 10 17:50:02 2018 +0100
+++ b/kallithea/tests/vcs/test_workdirs.py	Sat Feb 10 17:20:43 2018 +0100
@@ -1,6 +1,6 @@
 import datetime
 
-from kallithea.lib.vcs.utils.compat import unittest
+import pytest
 
 from kallithea.lib.vcs.nodes import FileNode
 
@@ -39,8 +39,7 @@
         return commits
 
     def test_get_branch_for_default_branch(self):
-        self.assertEqual(self.repo.workdir.get_branch(),
-            self.repo.DEFAULT_BRANCH_NAME)
+        assert self.repo.workdir.get_branch() == self.repo.DEFAULT_BRANCH_NAME
 
     def test_get_branch_after_adding_one(self):
         self.imc.add(FileNode('docs/index.txt',
@@ -50,7 +49,7 @@
             author=u'joe',
             branch='foobar',
         )
-        self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
+        assert self.repo.workdir.get_branch() == self.default_branch
 
     def test_get_changeset(self):
         old_head = self.repo.get_changeset()
@@ -61,28 +60,28 @@
             author=u'joe',
             branch='foobar',
         )
-        self.assertEqual(self.repo.workdir.get_branch(), self.default_branch)
+        assert self.repo.workdir.get_branch() == self.default_branch
         self.repo.workdir.checkout_branch('foobar')
-        self.assertEqual(self.repo.workdir.get_changeset(), head)
+        assert self.repo.workdir.get_changeset() == head
 
         # Make sure that old head is still there after update to default branch
         self.repo.workdir.checkout_branch(self.default_branch)
-        self.assertEqual(self.repo.workdir.get_changeset(), old_head)
+        assert self.repo.workdir.get_changeset() == old_head
 
     def test_checkout_branch(self):
         from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
         # first, 'foobranch' does not exist.
-        self.assertRaises(BranchDoesNotExistError, self.repo.workdir.checkout_branch,
-                          branch='foobranch')
+        with pytest.raises(BranchDoesNotExistError):
+            self.repo.workdir.checkout_branch(branch='foobranch')
         # create new branch 'foobranch'.
         self.imc.add(FileNode('file1', content='blah'))
         self.imc.commit(message=u'asd', author=u'john', branch='foobranch')
         # go back to the default branch
         self.repo.workdir.checkout_branch()
-        self.assertEqual(self.repo.workdir.get_branch(), self.backend_class.DEFAULT_BRANCH_NAME)
+        assert self.repo.workdir.get_branch() == self.backend_class.DEFAULT_BRANCH_NAME
         # checkout 'foobranch'
         self.repo.workdir.checkout_branch('foobranch')
-        self.assertEqual(self.repo.workdir.get_branch(), 'foobranch')
+        assert self.repo.workdir.get_branch() == 'foobranch'
 
 
 # For each backend create test case class
@@ -90,6 +89,5 @@
     attrs = {
         'backend_alias': alias,
     }
-    cls_name = ''.join(('%s branch test' % alias).title().split())
-    bases = (WorkdirTestCaseMixin, unittest.TestCase)
-    globals()[cls_name] = type(cls_name, bases, attrs)
+    cls_name = ''.join(('test %s branch' % alias).title().split())
+    globals()[cls_name] = type(cls_name, (WorkdirTestCaseMixin, ), attrs)