diff --git a/opentech/apply/review/tests/factories.py b/opentech/apply/review/tests/factories.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a4e3908c64f974a83695c61c830eea36cf73245
--- /dev/null
+++ b/opentech/apply/review/tests/factories.py
@@ -0,0 +1,29 @@
+import factory
+
+from opentech.apply.funds.tests.factories import ApplicationSubmissionFactory
+from opentech.apply.users.tests.factories import StaffFactory
+
+from ..models import Review
+from ..views import get_form_for_stage
+
+
+class ReviewDataFactory(factory.DictFactory):
+    @classmethod
+    def _build(cls, model_class, *args, **kwargs):
+        submission = kwargs.pop('submission')
+        form = get_form_for_stage(submission)(request=None, submission=None)
+        form_fields = {}
+        for field_name, field in form.fields.items():
+            form_fields[field_name] = 0
+
+        form_fields.update(**kwargs)
+        return super()._build(model_class, *args, **form_fields)
+
+
+class ReviewFactory(factory.DjangoModelFactory):
+    class Meta:
+        model = Review
+
+    submission = factory.SubFactory(ApplicationSubmissionFactory)
+    author = factory.SubFactory(StaffFactory)
+    review = factory.Dict({'submission': factory.SelfAttribute('..submission')}, dict_factory=ReviewDataFactory)
diff --git a/opentech/apply/review/tests/test_views.py b/opentech/apply/review/tests/test_views.py
new file mode 100644
index 0000000000000000000000000000000000000000..daac64e08d8f9f6356f319dc079da48d7b2d486c
--- /dev/null
+++ b/opentech/apply/review/tests/test_views.py
@@ -0,0 +1,68 @@
+from django.test import TestCase, RequestFactory
+from django.urls import reverse
+
+from opentech.apply.users.tests.factories import StaffFactory
+from .factories import ReviewFactory
+from opentech.apply.funds.tests.factories import ApplicationSubmissionFactory
+
+
+class BaseTestCase(TestCase):
+    url_name = ''
+    user_factory = None
+
+    def setUp(self):
+        self.factory = RequestFactory()
+        self.user = self.user_factory()
+        self.client.force_login(self.user)
+
+    def url(self, instance, view_name='review'):
+        full_url_name = self.url_name.format(view_name)
+        url = reverse(full_url_name, kwargs=self.get_kwargs(instance))
+        request = self.factory.get(url, secure=True)
+        return request.build_absolute_uri()
+
+    def get_page(self, instance, view_name='review'):
+        return self.client.get(self.url(instance, view_name), secure=True, follow=True)
+
+    def post_page(self, instance, data, view_name='review'):
+        return self.client.post(self.url(instance, view_name), data, secure=True, follow=True)
+
+    def refresh(self, instance):
+        return instance.__class__.objects.get(id=instance.id)
+
+
+class StaffReviewsTestCase(BaseTestCase):
+    user_factory = StaffFactory
+    url_name = 'funds:submissions:reviews:{}'
+
+    def get_kwargs(self, instance):
+        return {'pk': instance.id, 'submission_pk': instance.submission.id}
+
+    def test_can_access_review(self):
+        submission = ApplicationSubmissionFactory()
+        review = ReviewFactory(submission=submission, author=self.user)
+        response = self.get_page(review)
+        self.assertContains(response, review.submission.title)
+        self.assertContains(response, self.user.full_name)
+
+    def test_cant_access_other_review(self):
+        submission = ApplicationSubmissionFactory()
+        review = ReviewFactory(submission=submission)
+        response = self.get_page(review)
+        self.assertEqual(response.status_code, 403)
+
+
+class StaffReviewListingTestCase(BaseTestCase):
+    user_factory = StaffFactory
+    url_name = 'funds:submissions:reviews:{}'
+
+    def get_kwargs(self, instance):
+        return {'submission_pk': instance.id}
+
+    def test_can_access_review_listing(self):
+        submission = ApplicationSubmissionFactory()
+        reviews = ReviewFactory.create_batch(3, submission=submission)
+        response = self.get_page(submission, 'list')
+        self.assertContains(response, submission.title)
+        for review in reviews:
+            self.assertContains(response, review.author.full_name)