Test for a wide range of snapshot scenarios

This commit is contained in:
Eric Torres 2019-03-28 12:11:52 -07:00
parent c132d1c9d8
commit bc6f6bc503

View File

@ -1,153 +1,121 @@
import doctest import doctest
import unittest import unittest
from pathlib import PosixPath from hypothesis import given
from hypothesis.strategies import builds, lists, text
from pathlib import Path, PosixPath
from rbackup.hierarchy.repository import Repository from rbackup.hierarchy.repository import Repository
from rbackup.hierarchy.snapshot import Snapshot from rbackup.hierarchy.snapshot import Snapshot
from unittest.mock import patch, PropertyMock from unittest.mock import patch, MagicMock, PropertyMock
# ========== Constants ========== # ========== Constants ==========
TESTING_MODULE = "rbackup.hierarchy.repository" TESTING_PACKAGE = "rbackup.hierarchy"
REPO_MODULE = f"{TESTING_PACKAGE}.repository"
SS_MODULE = f"{TESTING_PACKAGE}.snapshot"
# ========== Functions ========== # ========== Functions ==========
def load_tests(loader, tests, ignore): def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(TESTING_MODULE)) tests.addTests(doctest.DocTestSuite(REPO_MODULE))
return tests return tests
# ========== Integration Tests ========== # ========== Integration Tests ==========
@patch.object(Repository, "snapshots", new_callable=PropertyMock) class TestRepositoryPreCreate(unittest.TestCase):
class TestEmptyRepository(unittest.TestCase): """Test properties of the Repository before running create_snapshot()."""
"""Test a repository that has no snapshots."""
def setUp(self): def setUp(self):
self.repo_basepath = "backup" self.patched_snapshot = patch(
self.repo = Repository(self.repo_basepath) f"{TESTING_PACKAGE}.repository.Snapshot", spec_set=Snapshot
self.new_snapshot_path = self.repo.snapshot_dir / "snapshot-new" )
self.created_snapshot = Snapshot(self.new_snapshot_path) self.patched_snapshots = patch.object(
Repository, "snapshots", new_callable=PropertyMock
)
self.patched_pickle = patch(f"{TESTING_PACKAGE}.repository.pickle")
def test_len_pre_create(self, repo_snapshots): self.repo_snapshots = self.patched_snapshots.start()
repo_snapshots.return_value = [] self.mocked_snapshot = self.patched_snapshot.start()
self.mocked_pickle = self.patched_pickle.start()
self.assertEqual(len(self.repo), 0) @given(lists(builds(Snapshot, text()), unique=True))
self.assertEqual(len(self.repo), len(repo_snapshots.return_value)) def test_empty(self, l):
repo = Repository('backup')
self.repo_snapshots.return_value = l
def test_iteration_pre_create(self, repo_snapshots): if l == []:
repo_snapshots.return_value = [] self.assertTrue(repo.empty)
else:
self.assertFalse(repo.empty)
with self.assertRaises(StopIteration): @given(lists(builds(Snapshot, text()), unique=True))
self.repo.__next__() def test_len(self, l):
repo = Repository('backup')
self.repo_snapshots.return_value = l
def test_subscript_pre_create(self, repo_snapshots): self.assertEqual(len(repo.snapshots), len(l))
repo_snapshots.return_value = []
with self.assertRaises(IndexError): @given(lists(builds(Snapshot, text()), unique=True))
self.repo[0] def test_current_snapshot(self, l):
self.repo_snapshots.return_value = l
repo = Repository('backup')
def test_curr_snapshot_pre_create(self, repo_snapshots): if l == []:
repo_snapshots.return_value = [] self.assertIsNone(repo.current_snapshot)
else:
self.assertIsNotNone(repo.current_snapshot)
self.assertIsInstance(repo.current_snapshot, Snapshot)
self.assertIsNone(self.repo.curr_snapshot) def tearDown(self):
self.patched_snapshots.stop()
def test_curr_snapshot_post_create(self, repo_snapshots): self.patched_snapshot.stop()
repo_snapshots.return_value = [] self.patched_pickle.stop()
snapshot_name = "new"
self.repo.create_snapshot(snapshot_name)
self.assertEqual(self.repo.curr_snapshot.path, self.created_snapshot.path)
def test_len_post_create(self, repo_snapshots):
repo_snapshots.return_value = [self.created_snapshot.path]
self.assertEqual(len(self.repo), len(repo_snapshots.return_value))
def test_iteration_post_create(self, repo_snapshots):
repo_snapshots.return_value = [self.created_snapshot]
result = []
for snapshot in self.repo:
result.append(snapshot)
self.assertListEqual(result, [self.created_snapshot])
def test_subscript_post_create(self, repo_snapshots):
repo_snapshots.return_value = [self.created_snapshot]
self.assertEqual(self.repo[0].path, self.new_snapshot_path)
@patch.object(Repository, "snapshots", new_callable=PropertyMock) class TestRepositoryPostCreate(unittest.TestCase):
class TestPopulatedRepository(unittest.TestCase): """Test properties of the Repository before running create_snapshot()."""
"""Test a repository that has no snapshots."""
def setUp(self): def setUp(self):
self.repo_basepath = "backup" self.patched_snapshot = patch(
self.repo = Repository(self.repo_basepath) f"{TESTING_PACKAGE}.repository.Snapshot", spec_set=Snapshot
)
self.patched_snapshots = patch.object(
Repository, "snapshots", new_callable=PropertyMock
)
self.patched_pickle = patch(f"{TESTING_PACKAGE}.repository.pickle")
self.new_snapshot_path_1 = self.repo.snapshot_dir / "snapshot-one" self.repo_snapshots = self.patched_snapshots.start()
self.new_snapshot_path_2 = self.repo.snapshot_dir / "snapshot-two" self.mocked_snapshot = self.patched_snapshot.start()
self.mocked_pickle = self.patched_pickle.start()
self.existing_snapshots = [ @given(lists(builds(Snapshot, text()), unique=True))
Snapshot(self.new_snapshot_path_1), def test_empty(self, l):
Snapshot(self.new_snapshot_path_2), self.repo_snapshots.return_value = l
] repo = Repository('backup')
def test_len_pre_create(self, repo_snapshots): repo.create_snapshot()
repo_snapshots.return_value = self.existing_snapshots
self.assertEqual(len(self.repo), len(repo_snapshots.return_value))
def test_iteration_pre_create(self, repo_snapshots): self.assertFalse(repo.empty)
repo_snapshots.return_value = self.existing_snapshots
# Exhaust the iterator first @given(lists(builds(Snapshot, text()), unique=True))
for iteration in range(0, len(self.existing_snapshots)): def test_len(self, l):
self.repo.__next__() self.repo_snapshots.return_value = l
repo = Repository('backup')
with self.assertRaises(StopIteration): repo.create_snapshot()
self.repo.__next__()
def test_subscript_pre_create(self, repo_snapshots): # Did the repository add the snapshot to its internal list?
repo_snapshots.return_value = self.existing_snapshots self.assertEqual(len(repo.snapshots), len(l))
with self.assertRaises(IndexError): @given(lists(builds(Snapshot, text()), unique=True))
self.repo[len(self.repo) + 1] def test_current_snapshot(self, l):
self.repo_snapshots.return_value = l
repo = Repository('backup')
with self.assertRaises(IndexError): new_snapshot = repo.create_snapshot()
self.repo[-1 * len(self.repo) - 1]
def test_curr_snapshot_pre_create(self, repo_snapshots): self.assertIs(new_snapshot, l[-1])
repo_snapshots.return_value = self.existing_snapshots self.assertIs(repo.current_snapshot, l[-1])
self.assertIsInstance(new_snapshot, Snapshot)
self.assertListEqual(self.repo.snapshots, self.existing_snapshots) def tearDown(self):
self.patched_snapshots.stop()
def test_curr_snapshot_post_create(self, repo_snapshots): self.patched_snapshot.stop()
"""We want to combine all of the tests before the snapshot self.patched_pickle.stop()
creation into one snapshot so as to not repeat the creation
of a new snapshot for each test."""
repo_snapshots.return_value = self.existing_snapshots
snapshot_name = "new"
self.repo.create_snapshot(snapshot_name)
self.new_snapshot_path_3 = self.repo.snapshot_dir / f"snapshot-{snapshot_name}"
self.assertEqual(self.repo.curr_snapshot.path, self.new_snapshot_path_3)
# Test that len works correctly
self.assertEqual(len(self.repo), len(self.existing_snapshots))
# Test that iteration works correctly
result = []
for snapshot in self.repo:
result.append(snapshot)
self.assertListEqual(result, self.existing_snapshots)
repo_snapshots.return_value = self.existing_snapshots
# Test that subscripts work correctly
self.assertEqual(self.repo[0].path, self.existing_snapshots[0].path)
self.assertEqual(self.repo[-1].path, self.existing_snapshots[-1].path)