Repository: apluslms/a-plus

Issue:
Use setUpTestData in tests 
`setUp` is ran before every test method but `setUpTestData` is run only once for the whole test class. Each test method is run in a transaction and rolled back at the end, so there is no need to re-create the database data for each method separately. Most of the time in unit tests seems to be spent on creating data for the tests, so it would be a massive speed up to reuse the data by using `setUpTestData`.

`setUpTestData` takes the class as an argument but it can be used similarly to `setUp`: just assign the properties to the class (e.g. `cls.instance = CourseInstance...`) and the property can be accessed normally through the object (e.g. `self.instance`).


Discussion:

Resolving patch:
diff --git a/lib/testdata.py b/lib/testdata.py
--- a/lib/testdata.py
+++ b/lib/testdata.py
@@ -19,10 +19,12 @@
 
 class CourseTestCase(TestCase):
 
-    def setUp(self):
-        self.setUpCourse()
-        self.setUpSubmissions()
+    @classmethod
+    def setUpTestData(cls):
+        cls.setUpCourse()
+        cls.setUpSubmissions()
 
+    @classmethod
     def setUpCourse(self):
 
         self.now = timezone.now()
@@ -140,6 +142,7 @@ def setUpCourse(self):
             max_group_size=2,
         )
 
+    @classmethod
     def setUpSubmissions(self):
 
         self.submission = Submission.objects.create(


Test patch:
diff --git a/apps/tests.py b/apps/tests.py
--- a/apps/tests.py
+++ b/apps/tests.py
@@ -13,25 +13,26 @@
 
 class AppsTest(TestCase):
 
-    def setUp(self):
-        self.client = Client()
-        self.course = Course.objects.create(name="Test", code="test", url="test")
-        self.instance = CourseInstance.objects.create(course=self.course,
+    @classmethod
+    def setUpTestData(cls):
+        cls.client = Client()
+        cls.course = Course.objects.create(name="Test", code="test", url="test")
+        cls.instance = CourseInstance.objects.create(course=cls.course,
                                                       instance_name="Ins",
                                                       starting_time="2000-01-01T12:00:00.000Z",
                                                       ending_time="2020-01-01T12:00:00.000Z")
 
-        self.html_plugin = HTMLPlugin.objects.create(container=self.instance,
+        cls.html_plugin = HTMLPlugin.objects.create(container=cls.instance,
                                                      title="HTML Plugin",
                                                      views="exercise,course_instance",
                                                      content=HTML_PLUGIN_CONTENT)
 
-        self.rss_plugin = RSSPlugin.objects.create(container=self.instance,
+        cls.rss_plugin = RSSPlugin.objects.create(container=cls.instance,
                                                    title="RSS Plugin",
                                                    views="course_instance",
                                                    feed_url=RSS_PLUGIN_ADDRESS)
 
-        self.iframe_plugin = ExternalIFramePlugin.objects.create(container=self.instance,
+        cls.iframe_plugin = ExternalIFramePlugin.objects.create(container=cls.instance,
                                                                  title="Iframe Plugin",
                                                                  views="exercise",
                                                                  service_url=IFRAME_PLUGIN_ADDRESS,
diff --git a/course/api/tests.py b/course/api/tests.py
--- a/course/api/tests.py
+++ b/course/api/tests.py
@@ -1,13 +1,11 @@
-from django.test import TestCase, override_settings
+from django.test import override_settings
 from rest_framework.test import APIClient
 
 from course.models import CourseInstance
+from ..tests import CourseTestCase
 
-
-class CourseInstanceAPITest(TestCase):
-    # use same setUp as for normal tests
-    from ..tests import CourseTest # pylint: disable=import-outside-toplevel
-    setUp = CourseTest.setUp
+class CourseInstanceAPITest(CourseTestCase):
+    # uses the same setUpTestData as for normal tests
 
     @override_settings(BASE_URL="http://testserver/")
     def test_get_courselist(self):
diff --git a/course/test_visibility_enroll.py b/course/test_visibility_enroll.py
--- a/course/test_visibility_enroll.py
+++ b/course/test_visibility_enroll.py
@@ -17,108 +17,109 @@ class CourseVisibilityTest(TestCase):
     There are also some tests about enrollment.
     """
 
-    def setUp(self):
-        self.user = User(username="testUser") # not enrolled in the course
-        self.user.set_password("testUser")
-        self.user.save()
-        self.user.userprofile.student_id = '123456'
-        self.user.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user.userprofile.save()
-
-        self.student = User(username="student") # enrolled in the course
-        self.student.set_password("student")
-        self.student.save()
-        self.student.userprofile.student_id = '654321'
-        self.student.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.student.userprofile.save()
-
-        self.course = Course.objects.create(
+    @classmethod
+    def setUpTestData(cls):
+        cls.user = User(username="testUser") # not enrolled in the course
+        cls.user.set_password("testUser")
+        cls.user.save()
+        cls.user.userprofile.student_id = '123456'
+        cls.user.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user.userprofile.save()
+
+        cls.student = User(username="student") # enrolled in the course
+        cls.student.set_password("student")
+        cls.student.save()
+        cls.student.userprofile.student_id = '654321'
+        cls.student.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.student.userprofile.save()
+
+        cls.course = Course.objects.create(
             name="Test course",
             code="123456",
             url="Course-Url",
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.tomorrow + timedelta(days=1)
-        self.yesterday = self.today - timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.tomorrow + timedelta(days=1)
+        cls.yesterday = cls.today - timedelta(days=1)
 
         # course instances with different view_access_to settings
-        self.public_course_instance = CourseInstance.objects.create(
+        cls.public_course_instance = CourseInstance.objects.create(
             instance_name="Public",
-            starting_time=self.yesterday,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.yesterday,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="public",
             view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
             enrollment_audience=CourseInstance.ENROLLMENT_AUDIENCE.INTERNAL_USERS,
         )
 
-        self.all_regist_course_instance = CourseInstance.objects.create(
+        cls.all_regist_course_instance = CourseInstance.objects.create(
             instance_name="All registered users",
-            starting_time=self.yesterday,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.yesterday,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="allregistered",
             view_content_to=CourseInstance.VIEW_ACCESS.ALL_REGISTERED,
             enrollment_audience=CourseInstance.ENROLLMENT_AUDIENCE.INTERNAL_USERS,
         )
 
-        self.enroll_audience_course_instance = CourseInstance.objects.create(
+        cls.enroll_audience_course_instance = CourseInstance.objects.create(
             instance_name="Enrollment audience",
-            starting_time=self.yesterday,
-            ending_time=self.two_days_from_now,
-            course=self.course,
+            starting_time=cls.yesterday,
+            ending_time=cls.two_days_from_now,
+            course=cls.course,
             url="enrollmentaudience",
             view_content_to=CourseInstance.VIEW_ACCESS.ENROLLMENT_AUDIENCE,
             enrollment_audience=CourseInstance.ENROLLMENT_AUDIENCE.INTERNAL_USERS,
         )
 
-        self.enrolled_course_instance = CourseInstance.objects.create(
+        cls.enrolled_course_instance = CourseInstance.objects.create(
             instance_name="Enrolled",
-            starting_time=self.yesterday,
-            ending_time=self.two_days_from_now,
-            course=self.course,
+            starting_time=cls.yesterday,
+            ending_time=cls.two_days_from_now,
+            course=cls.course,
             url="enrolled",
             view_content_to=CourseInstance.VIEW_ACCESS.ENROLLED,
             enrollment_audience=CourseInstance.ENROLLMENT_AUDIENCE.INTERNAL_USERS,
         )
-        self.course_instances = [self.public_course_instance, self.all_regist_course_instance,
-            self.enroll_audience_course_instance, self.enrolled_course_instance]
+        cls.course_instances = [cls.public_course_instance, cls.all_regist_course_instance,
+            cls.enroll_audience_course_instance, cls.enrolled_course_instance]
 
         # enrollment
-        for instance in self.course_instances:
-            instance.enroll_student(self.student)
+        for instance in cls.course_instances:
+            instance.enroll_student(cls.student)
 
         # module/exercise round for each course instance
-        self.course_modules = {}
-        for instance in self.course_instances:
-            self.course_modules[instance.id] = CourseModule.objects.create(
+        cls.course_modules = {}
+        for instance in cls.course_instances:
+            cls.course_modules[instance.id] = CourseModule.objects.create(
                 name="Test module",
                 url="test-module",
                 points_to_pass=10,
                 course_instance=instance,
-                opening_time=self.today,
-                closing_time=self.tomorrow,
+                opening_time=cls.today,
+                closing_time=cls.tomorrow,
             )
 
         # category
-        self.categories = {}
-        for instance in self.course_instances:
-            self.categories[instance.id] = LearningObjectCategory.objects.create(
+        cls.categories = {}
+        for instance in cls.course_instances:
+            cls.categories[instance.id] = LearningObjectCategory.objects.create(
                 name="Test category",
                 course_instance=instance,
                 points_to_pass=0,
             )
 
         # learning objects
-        self.learning_objects = {}
-        for instance in self.course_instances:
+        cls.learning_objects = {}
+        for instance in cls.course_instances:
             lobjects = []
             chapter = CourseChapter.objects.create(
                 name="Test chapter",
-                course_module=self.course_modules[instance.id],
-                category=self.categories[instance.id],
+                course_module=cls.course_modules[instance.id],
+                category=cls.categories[instance.id],
                 url='chapter1',
             )
             lobjects.append(chapter)
@@ -126,8 +127,8 @@ def setUp(self):
                 name="Embedded exercise",
                 parent=chapter,
                 status=LearningObject.STATUS.UNLISTED,
-                course_module=self.course_modules[instance.id],
-                category=self.categories[instance.id],
+                course_module=cls.course_modules[instance.id],
+                category=cls.categories[instance.id],
                 url='embedexercise',
                 max_submissions=10,
                 max_points=10,
@@ -135,27 +136,27 @@ def setUp(self):
             ))
             lobjects.append(BaseExercise.objects.create(
                 name="Normal exercise",
-                course_module=self.course_modules[instance.id],
-                category=self.categories[instance.id],
+                course_module=cls.course_modules[instance.id],
+                category=cls.categories[instance.id],
                 url='normalexercise',
                 max_submissions=10,
                 max_points=10,
                 points_to_pass=0,
             ))
-            self.learning_objects[instance.id] = lobjects
+            cls.learning_objects[instance.id] = lobjects
 
         # submissions
-        self.submissions = {}
-        for _course_instance_id, exercises in self.learning_objects.items():
+        cls.submissions = {}
+        for _course_instance_id, exercises in cls.learning_objects.items():
             for exercise in exercises:
                 if not exercise.is_submittable:
                     continue
-                self.submissions[exercise.id] = []
+                cls.submissions[exercise.id] = []
                 submission = Submission.objects.create(
                     exercise=exercise,
                 )
-                submission.submitters.add(self.student.userprofile)
-                self.submissions[exercise.id].append(submission)
+                submission.submitters.add(cls.student.userprofile)
+                cls.submissions[exercise.id].append(submission)
 
         # disable all logging
         logging.disable(logging.CRITICAL)
diff --git a/course/tests.py b/course/tests.py
--- a/course/tests.py
+++ b/course/tests.py
@@ -12,158 +12,161 @@
 from exercise.models import BaseExercise, Submission
 from exercise.exercise_models import LearningObject
 
-
-class CourseTest(TestCase):
-    def setUp(self):
-        self.client = Client()
-
-        self.user = User(username="testUser")
-        self.user.set_password("testPassword")
-        self.user.save()
-
-        self.grader = User(username="grader", is_staff=True)
-        self.grader.set_password("graderPassword")
-        self.grader.save()
-
-        self.superuser = User(username="staff", is_staff=True, is_superuser=True)
-        self.superuser.set_password("staffPassword")
-        self.superuser.save()
-
-        self.user1 = User(username="testUser1")
-        self.user1.set_password("testPassword")
-        self.user1.save()
-        self.user1.userprofile.student_id = '333333'
-        self.user1.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user1.userprofile.save()
-
-        self.user2 = User(username="testUser2")
-        self.user2.set_password("testPassword")
-        self.user2.save()
-        self.user2.userprofile.student_id = '555555'
-        self.user2.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user2.userprofile.save()
-
-        self.course = Course.objects.create(
+class CourseTestCase(TestCase):
+
+    @classmethod
+    def setUpTestData(cls):
+        cls.client = Client()
+
+        cls.user = User(username="testUser")
+        cls.user.set_password("testPassword")
+        cls.user.save()
+
+        cls.grader = User(username="grader", is_staff=True)
+        cls.grader.set_password("graderPassword")
+        cls.grader.save()
+
+        cls.superuser = User(username="staff", is_staff=True, is_superuser=True)
+        cls.superuser.set_password("staffPassword")
+        cls.superuser.save()
+
+        cls.user1 = User(username="testUser1")
+        cls.user1.set_password("testPassword")
+        cls.user1.save()
+        cls.user1.userprofile.student_id = '333333'
+        cls.user1.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user1.userprofile.save()
+
+        cls.user2 = User(username="testUser2")
+        cls.user2.set_password("testPassword")
+        cls.user2.save()
+        cls.user2.userprofile.student_id = '555555'
+        cls.user2.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user2.userprofile.save()
+
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.tomorrow + timedelta(days=1)
-        self.yesterday = self.today - timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.tomorrow + timedelta(days=1)
+        cls.yesterday = cls.today - timedelta(days=1)
 
-        self.past_course_instance = CourseInstance.objects.create(
+        cls.past_course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011 day 0",
-            starting_time=self.yesterday,
-            ending_time=self.today,
-            course=self.course,
+            starting_time=cls.yesterday,
+            ending_time=cls.today,
+            course=cls.course,
             url="T-00.1000_d0"
         )
 
-        self.current_course_instance = CourseInstance.objects.create(
+        cls.current_course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1",
             sis_id=123
         )
 
-        self.future_course_instance = CourseInstance.objects.create(
+        cls.future_course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011 day 2",
-            starting_time=self.tomorrow,
-            ending_time=self.two_days_from_now,
-            course=self.course,
+            starting_time=cls.tomorrow,
+            ending_time=cls.two_days_from_now,
+            course=cls.course,
             url="T-00.1000_d2"
         )
 
-        self.hidden_course_instance = CourseInstance.objects.create(
+        cls.hidden_course_instance = CourseInstance.objects.create(
             instance_name="Secret super course",
-            starting_time=self.tomorrow,
-            ending_time=self.two_days_from_now,
-            course=self.course,
+            starting_time=cls.tomorrow,
+            ending_time=cls.two_days_from_now,
+            course=cls.course,
             url="T-00.1000_hidden",
             visible_to_students=False
         )
 
-        self.course_module = CourseModule.objects.create(
+        cls.course_module = CourseModule.objects.create(
             name="test module",
             url="test-module",
             points_to_pass=10,
-            course_instance=self.current_course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow
+            course_instance=cls.current_course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow
         )
 
-        self.course_module_with_reading_open = CourseModule.objects.create(
+        cls.course_module_with_reading_open = CourseModule.objects.create(
             name="test module",
             url="test-module-reading-open",
             points_to_pass=10,
-            course_instance=self.current_course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow,
-            reading_opening_time=self.yesterday
+            course_instance=cls.current_course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow,
+            reading_opening_time=cls.yesterday
         )
 
-        self.course_module_with_late_submissions_allowed = CourseModule.objects.create(
+        cls.course_module_with_late_submissions_allowed = CourseModule.objects.create(
             name="test module",
             url="test-module-late",
             points_to_pass=50,
-            course_instance=self.current_course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow,
+            course_instance=cls.current_course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow,
             late_submissions_allowed=True,
-            late_submission_deadline=self.two_days_from_now,
+            late_submission_deadline=cls.two_days_from_now,
             late_submission_penalty=0.2
         )
 
-        self.learning_object_category = LearningObjectCategory.objects.create(
+        cls.learning_object_category = LearningObjectCategory.objects.create(
             name="test category",
-            course_instance=self.current_course_instance,
+            course_instance=cls.current_course_instance,
             points_to_pass=5
         )
 
-        #self.hidden_learning_object_category = LearningObjectCategory.objects.create(
+        #cls.hidden_learning_object_category = LearningObjectCategory.objects.create(
         #    name="hidden category",
-        #    course_instance=self.current_course_instance
+        #    course_instance=cls.current_course_instance
         #)
-        #self.hidden_learning_object_category.hidden_to.add(self.user.userprofile)
+        #cls.hidden_learning_object_category.hidden_to.add(cls.user.userprofile)
 
-        self.learning_object = LearningObject.objects.create(
+        cls.learning_object = LearningObject.objects.create(
             name="test learning object",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url='l1',
         )
 
-        self.broken_learning_object = LearningObject.objects.create(
+        cls.broken_learning_object = LearningObject.objects.create(
             name="test learning object",
-            course_module=self.course_module_with_late_submissions_allowed,
-            category=self.learning_object_category,
+            course_module=cls.course_module_with_late_submissions_allowed,
+            category=cls.learning_object_category,
             url='l2',
         )
 
-        self.base_exercise = BaseExercise.objects.create(
+        cls.base_exercise = BaseExercise.objects.create(
             name="test exercise",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             service_url="http://localhost/",
             url='b1',
         )
 
-        self.submission = Submission.objects.create(
-            exercise=self.base_exercise,
-            grader=self.grader.userprofile
+        cls.submission = Submission.objects.create(
+            exercise=cls.base_exercise,
+            grader=cls.grader.userprofile
         )
-        self.submission.submitters.add(self.user.userprofile)
+        cls.submission.submitters.add(cls.user.userprofile)
 
-        self.course_hook = CourseHook.objects.create(
+        cls.course_hook = CourseHook.objects.create(
             hook_url="test_hook_url",
-            course_instance=self.current_course_instance
+            course_instance=cls.current_course_instance
         )
 
+class CourseTest(CourseTestCase):
+
     def test_course_instance_open(self):
         self.assertFalse(self.past_course_instance.is_open())
         self.assertTrue(self.current_course_instance.is_open())
diff --git a/deviations/tests.py b/deviations/tests.py
--- a/deviations/tests.py
+++ b/deviations/tests.py
@@ -21,72 +21,73 @@
 
 
 class DeviationsTest(TestCase):
-    def setUp(self):
-        self.teacher = User(username="staff", is_staff=True)
-        self.teacher.set_password("staffPassword")
-        self.teacher.save()
+    @classmethod
+    def setUpTestData(cls):
+        cls.teacher = User(username="staff", is_staff=True)
+        cls.teacher.set_password("staffPassword")
+        cls.teacher.save()
 
-        self.client = Client()
+        cls.client = Client()
 
-        self.user = User(username="testUser", first_name="First", last_name="Last")
-        self.user.set_password("testPassword")
-        self.user.save()
+        cls.user = User(username="testUser", first_name="First", last_name="Last")
+        cls.user.set_password("testPassword")
+        cls.user.save()
 
-        self.user_2 = User(username="testUser2", first_name="First2", last_name="Last2")
-        self.user_2.set_password("testPassword2")
-        self.user_2.save()
+        cls.user_2 = User(username="testUser2", first_name="First2", last_name="Last2")
+        cls.user_2.set_password("testPassword2")
+        cls.user_2.save()
 
-        self.course = Course.objects.create(
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url",
         )
 
         # Truncate the datetime to seconds to make testing deadline deviations more convenient
-        self.today = timezone.now().replace(microsecond=0)
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.today + timedelta(days=2)
+        cls.today = timezone.now().replace(microsecond=0)
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.today + timedelta(days=2)
 
-        self.course_instance = CourseInstance.objects.create(
+        cls.course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1",
         )
 
-        self.course_instance.enroll_student(self.user)
-        self.course_instance.enroll_student(self.user_2)
-        self.course_instance.add_teacher(self.teacher.userprofile)
+        cls.course_instance.enroll_student(cls.user)
+        cls.course_instance.enroll_student(cls.user_2)
+        cls.course_instance.add_teacher(cls.teacher.userprofile)
 
-        self.course_module = CourseModule.objects.create(
+        cls.course_module = CourseModule.objects.create(
             name="test module",
             url="test-module",
             points_to_pass=15,
-            course_instance=self.course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow,
+            course_instance=cls.course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow,
         )
 
-        self.course_module_2 = CourseModule.objects.create(
+        cls.course_module_2 = CourseModule.objects.create(
             name="test module 2",
             url="test-module-2",
             points_to_pass=15,
-            course_instance=self.course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow,
+            course_instance=cls.course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow,
         )
 
-        self.learning_object_category = LearningObjectCategory.objects.create(
+        cls.learning_object_category = LearningObjectCategory.objects.create(
             name="test category",
-            course_instance=self.course_instance,
+            course_instance=cls.course_instance,
             points_to_pass=5,
         )
 
-        self.exercise_with_attachment = ExerciseWithAttachment.objects.create(
+        cls.exercise_with_attachment = ExerciseWithAttachment.objects.create(
             name="test exercise 3",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             max_points=50,
             points_to_pass=50,
             max_submissions=1,
@@ -95,10 +96,10 @@ def setUp(self):
             url="test_exercise_1",
         )
 
-        self.exercise_with_attachment_2 = ExerciseWithAttachment.objects.create(
+        cls.exercise_with_attachment_2 = ExerciseWithAttachment.objects.create(
             name="test exercise 4",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             max_points=50,
             points_to_pass=50,
             max_submissions=1,
@@ -107,55 +108,55 @@ def setUp(self):
             url="test_exercise_2",
         )
 
-        self.module_2_exercise_1 = BaseExercise.objects.create(
+        cls.module_2_exercise_1 = BaseExercise.objects.create(
             name="module 2 test exercise 1",
-            course_module=self.course_module_2,
-            category=self.learning_object_category,
+            course_module=cls.course_module_2,
+            category=cls.learning_object_category,
             max_points=50,
             points_to_pass=50,
             max_submissions=1,
             url="module_2_exercise_1",
         )
 
-        self.module_2_exercise_2 = BaseExercise.objects.create(
+        cls.module_2_exercise_2 = BaseExercise.objects.create(
             name="module 2 test exercise 2",
-            course_module=self.course_module_2,
-            category=self.learning_object_category,
+            course_module=cls.course_module_2,
+            category=cls.learning_object_category,
             max_points=50,
             points_to_pass=50,
             max_submissions=1,
             url="module_2_exercise_2",
         )
 
-        self.user_tag = UserTag.objects.create(
-            course_instance=self.course_instance,
+        cls.user_tag = UserTag.objects.create(
+            course_instance=cls.course_instance,
             name='tag_1',
         )
 
-        self.user_tagging = UserTagging.objects.create(
-            tag=self.user_tag,
-            user=self.user.userprofile,
-            course_instance=self.course_instance,
+        cls.user_tagging = UserTagging.objects.create(
+            tag=cls.user_tag,
+            user=cls.user.userprofile,
+            course_instance=cls.course_instance,
         )
 
-        self.deadline_rule_deviation_u1_e1 = DeadlineRuleDeviation.objects.create(
-            exercise=self.exercise_with_attachment,
-            submitter=self.user.userprofile,
-            granter=self.teacher.userprofile,
+        cls.deadline_rule_deviation_u1_e1 = DeadlineRuleDeviation.objects.create(
+            exercise=cls.exercise_with_attachment,
+            submitter=cls.user.userprofile,
+            granter=cls.teacher.userprofile,
             extra_seconds=24*60*60, # One day
         )
 
-        self.deadline_rule_deviation_u1_e2 = DeadlineRuleDeviation.objects.create(
-            exercise=self.exercise_with_attachment_2,
-            submitter=self.user.userprofile,
-            granter=self.teacher.userprofile,
+        cls.deadline_rule_deviation_u1_e2 = DeadlineRuleDeviation.objects.create(
+            exercise=cls.exercise_with_attachment_2,
+            submitter=cls.user.userprofile,
+            granter=cls.teacher.userprofile,
             extra_seconds=2*24*60*60, # Two days
         )
 
-        self.deadline_rule_deviation_u2_e1 = DeadlineRuleDeviation.objects.create(
-            exercise=self.exercise_with_attachment,
-            submitter=self.user_2.userprofile,
-            granter=self.teacher.userprofile,
+        cls.deadline_rule_deviation_u2_e1 = DeadlineRuleDeviation.objects.create(
+            exercise=cls.exercise_with_attachment,
+            submitter=cls.user_2.userprofile,
+            granter=cls.teacher.userprofile,
             extra_seconds=3*24*60*60, # Three days
         )
 
diff --git a/edit_course/tests.py b/edit_course/tests.py
--- a/edit_course/tests.py
+++ b/edit_course/tests.py
@@ -128,8 +128,9 @@ def test_clone_from_sis(self):
 
 class BatchAssessTest(CourseTestCase):
 
-    def setUp(self):
-        self.setUpCourse()
+    @classmethod
+    def setUpTestData(cls):
+        cls.setUpCourse()
 
     def test_batch_assess(self):
 
diff --git a/exercise/api/csv/tests.py b/exercise/api/csv/tests.py
--- a/exercise/api/csv/tests.py
+++ b/exercise/api/csv/tests.py
@@ -11,104 +11,105 @@
 from .views import CourseResultsDataViewSet
 
 class CourseResultsDataViewSetTest(TestCase):
-    def setUp(self):
+    @classmethod
+    def setUpTestData(cls):
         # Make a student
-        self.student = User(username="testUser", first_name="Superb",
+        cls.student = User(username="testUser", first_name="Superb",
                             last_name="Student", email="test@aplus.com")
-        self.student.set_password("testPassword")
-        self.student.save()
-        self.student_profile = self.student.userprofile
-        self.student_profile.student_id = "12345X"
-        self.student_profile.save()
+        cls.student.set_password("testPassword")
+        cls.student.save()
+        cls.student_profile = cls.student.userprofile
+        cls.student_profile.student_id = "12345X"
+        cls.student_profile.save()
 
-        self.student2 = User(username="testUser2", first_name="Superb",
+        cls.student2 = User(username="testUser2", first_name="Superb",
                             last_name="Student", email="test@aplus.com")
-        self.student2.set_password("testPassword")
-        self.student2.save()
-        self.student_profile2 = self.student2.userprofile
-        self.student_profile2.student_id = "12345Y"
-        self.student_profile2.save()
+        cls.student2.set_password("testPassword")
+        cls.student2.save()
+        cls.student_profile2 = cls.student2.userprofile
+        cls.student_profile2.student_id = "12345Y"
+        cls.student_profile2.save()
 
         # Make a course and course instance
-        self.course = Course.objects.create(
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
 
-        self.course_instance1 = CourseInstance.objects.create(
+        cls.course_instance1 = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1"
         )
 
         # Add learning object categories to course
-        self.chapter_category = LearningObjectCategory.objects.create(
+        cls.chapter_category = LearningObjectCategory.objects.create(
             name="chapter",
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
-        self.learning_object_category1 = LearningObjectCategory.objects.create(
+        cls.learning_object_category1 = LearningObjectCategory.objects.create(
             name="test category 1",
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
-        self.mandatory_category1 = LearningObjectCategory.objects.create(
+        cls.mandatory_category1 = LearningObjectCategory.objects.create(
             name="mandatory category 1",
             confirm_the_level=True,
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
 
-        self.module1 = CourseModule.objects.create(
+        cls.module1 = CourseModule.objects.create(
             name="module1",
             url="module1",
-            course_instance=self.course_instance1,
+            course_instance=cls.course_instance1,
         )
 
         # Add learning objects to module1
-        self.learning_object1 = BaseExercise.objects.create(
+        cls.learning_object1 = BaseExercise.objects.create(
             name="learning object 1",
             url="lo1",
-            course_module=self.module1,
-            category=self.learning_object_category1,
+            course_module=cls.module1,
+            category=cls.learning_object_category1,
         )
-        self.mandatory_learning_object1 = BaseExercise.objects.create(
+        cls.mandatory_learning_object1 = BaseExercise.objects.create(
             name="mandatory learning object 1",
             url="mlo1",
-            course_module=self.module1,
-            category=self.mandatory_category1,
+            course_module=cls.module1,
+            category=cls.mandatory_category1,
             points_to_pass=1,
         )
 
         # Add learning objects to module1
-        self.chapter1 = CourseChapter.objects.create(
+        cls.chapter1 = CourseChapter.objects.create(
             name="chapter 1",
             url="c1",
-            course_module=self.module1,
-            category=self.chapter_category,
+            course_module=cls.module1,
+            category=cls.chapter_category,
         )
-        self.c1_learning_object1 = BaseExercise.objects.create(
+        cls.c1_learning_object1 = BaseExercise.objects.create(
             name="c1 learning object 1",
             url="c1lo1",
-            course_module=self.module1,
-            parent=self.chapter1,
-            category=self.learning_object_category1,
+            course_module=cls.module1,
+            parent=cls.chapter1,
+            category=cls.learning_object_category1,
         )
-        self.c1_mandatory_learning_object1 = BaseExercise.objects.create(
+        cls.c1_mandatory_learning_object1 = BaseExercise.objects.create(
             name="c1 mandatory learning object 1",
             url="c1mlo1",
-            course_module=self.module1,
-            parent=self.chapter1,
-            category=self.mandatory_category1,
+            course_module=cls.module1,
+            parent=cls.chapter1,
+            category=cls.mandatory_category1,
             points_to_pass=1,
         )
 
         # Add a student to course instance
-        self.course_instance1.enroll_student(self.student_profile.user)
-        self.course_instance1.enroll_student(self.student_profile2.user)
+        cls.course_instance1.enroll_student(cls.student_profile.user)
+        cls.course_instance1.enroll_student(cls.student_profile2.user)
 
     def test_get_submissions_query_unconfirmed_points(self):
         def query(unconfirmed: bool):
diff --git a/exercise/api/tests.py b/exercise/api/tests.py
--- a/exercise/api/tests.py
+++ b/exercise/api/tests.py
@@ -7,46 +7,47 @@
 from datetime import timedelta
 
 class ExerciceSubmissionAPITest(TestCase):
-    def setUp(self):
+    @classmethod
+    def setUpTestData(cls):
         # Make a student
-        self.student = User(username="testUser", first_name="Superb",
+        cls.student = User(username="testUser", first_name="Superb",
                             last_name="Student", email="test@aplus.com")
-        self.student.set_password("testPassword")
-        self.student.save()
-        self.student_profile = self.student.userprofile
-        self.student_profile.student_id = "12345X"
-        self.student_profile.save()
+        cls.student.set_password("testPassword")
+        cls.student.save()
+        cls.student_profile = cls.student.userprofile
+        cls.student_profile.student_id = "12345X"
+        cls.student_profile.save()
 
         # Make a course and course instance
-        self.course = Course.objects.create(
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.tomorrow + timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.tomorrow + timedelta(days=1)
 
-        self.course_instance1 = CourseInstance.objects.create(
+        cls.course_instance1 = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1"
         )
 
         # Add learning object category to course
-        self.learning_object_category1 = LearningObjectCategory.objects.create(
+        cls.learning_object_category1 = LearningObjectCategory.objects.create(
             name="test category 1",
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
 
         # Add learning object to that category
-        #self.learning_object_category1.
+        #cls.learning_object_category1.
 
         # Add a student to course instance
-        self.course_instance1.enroll_student(self.student_profile.user)
+        cls.course_instance1.enroll_student(cls.student_profile.user)
 
     # Not finished
     def test_post_submission(self):
diff --git a/exercise/tests.py b/exercise/tests.py
--- a/exercise/tests.py
+++ b/exercise/tests.py
@@ -27,135 +27,136 @@
 from lib.helpers import build_aplus_url
 
 class ExerciseTestBase(TestCase):
-    def setUp(self): # pylint: disable=too-many-statements
-        self.user = User(username="testUser", first_name="First", last_name="Last")
-        self.user.set_password("testPassword")
-        self.user.save()
-        self.user.userprofile.student_id = '123456'
-        self.user.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user.userprofile.save()
-
-        self.grader = User(username="grader")
-        self.grader.set_password("graderPassword")
-        self.grader.save()
-
-        self.teacher = User(username="staff", is_staff=True)
-        self.teacher.set_password("staffPassword")
-        self.teacher.save()
-
-        self.user2 = User(username="testUser2", first_name="Strange", last_name="Fellow")
-        self.user2.set_password("testPassword2")
-        self.user2.save()
-        self.user2.userprofile.student_id = '654321'
-        self.user2.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user2.userprofile.save()
-
-        self.course = Course.objects.create(
+    @classmethod
+    def setUpTestData(cls): # pylint: disable=too-many-statements
+        cls.user = User(username="testUser", first_name="First", last_name="Last")
+        cls.user.set_password("testPassword")
+        cls.user.save()
+        cls.user.userprofile.student_id = '123456'
+        cls.user.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user.userprofile.save()
+
+        cls.grader = User(username="grader")
+        cls.grader.set_password("graderPassword")
+        cls.grader.save()
+
+        cls.teacher = User(username="staff", is_staff=True)
+        cls.teacher.set_password("staffPassword")
+        cls.teacher.save()
+
+        cls.user2 = User(username="testUser2", first_name="Strange", last_name="Fellow")
+        cls.user2.set_password("testPassword2")
+        cls.user2.save()
+        cls.user2.userprofile.student_id = '654321'
+        cls.user2.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user2.userprofile.save()
+
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.yesterday = self.today - timedelta(days=1)
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.tomorrow + timedelta(days=1)
-        self.three_days_from_now = self.two_days_from_now + timedelta(days=1)
+        cls.today = timezone.now()
+        cls.yesterday = cls.today - timedelta(days=1)
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.tomorrow + timedelta(days=1)
+        cls.three_days_from_now = cls.two_days_from_now + timedelta(days=1)
 
-        self.course_instance = CourseInstance.objects.create(
+        cls.course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            enrollment_starting_time=self.yesterday,
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            enrollment_starting_time=cls.yesterday,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1",
             view_content_to=CourseInstance.VIEW_ACCESS.ENROLLMENT_AUDIENCE,
         )
-        self.course_instance.add_teacher(self.teacher.userprofile)
-        self.course_instance.add_assistant(self.grader.userprofile)
+        cls.course_instance.add_teacher(cls.teacher.userprofile)
+        cls.course_instance.add_assistant(cls.grader.userprofile)
 
-        self.course_module = CourseModule.objects.create(
+        cls.course_module = CourseModule.objects.create(
             name="test module",
             url="test-module",
             points_to_pass=15,
-            course_instance=self.course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow
+            course_instance=cls.course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow
         )
 
-        self.course_module_with_late_submissions_allowed = CourseModule.objects.create(
+        cls.course_module_with_late_submissions_allowed = CourseModule.objects.create(
             name="test module",
             url="test-module-late",
             points_to_pass=50,
-            course_instance=self.course_instance,
-            opening_time=self.today,
-            closing_time=self.tomorrow,
+            course_instance=cls.course_instance,
+            opening_time=cls.today,
+            closing_time=cls.tomorrow,
             late_submissions_allowed=True,
-            late_submission_deadline=self.two_days_from_now,
+            late_submission_deadline=cls.two_days_from_now,
             late_submission_penalty=0.2
         )
 
-        self.old_course_module = CourseModule.objects.create(
+        cls.old_course_module = CourseModule.objects.create(
             name="test module",
             url="test-module-old",
             points_to_pass=15,
-            course_instance=self.course_instance,
-            opening_time=self.yesterday,
-            closing_time=self.today
+            course_instance=cls.course_instance,
+            opening_time=cls.yesterday,
+            closing_time=cls.today
         )
 
-        self.reading_open_course_module = CourseModule.objects.create(
+        cls.reading_open_course_module = CourseModule.objects.create(
             name="test module",
             url="test-module-reading-open",
             points_to_pass=15,
-            course_instance=self.course_instance,
-            reading_opening_time=self.yesterday,
-            opening_time=self.tomorrow,
-            closing_time=self.two_days_from_now
+            course_instance=cls.course_instance,
+            reading_opening_time=cls.yesterday,
+            opening_time=cls.tomorrow,
+            closing_time=cls.two_days_from_now
         )
 
-        self.learning_object_category = LearningObjectCategory.objects.create(
+        cls.learning_object_category = LearningObjectCategory.objects.create(
             name="test category",
-            course_instance=self.course_instance,
+            course_instance=cls.course_instance,
             points_to_pass=5
         )
 
-        self.hidden_learning_object_category = LearningObjectCategory.objects.create(
+        cls.hidden_learning_object_category = LearningObjectCategory.objects.create(
             name="hidden category",
-            course_instance=self.course_instance
+            course_instance=cls.course_instance
         )
-        #self.hidden_learning_object_category.hidden_to.add(self.user.userprofile)
+        #cls.hidden_learning_object_category.hidden_to.add(cls.user.userprofile)
 
-        self.learning_object = LearningObject.objects.create(
+        cls.learning_object = LearningObject.objects.create(
             name="test learning object",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url="l1",
         )
 
         # Learning object names are not unique, so this object really is not
         # broken despite the variable name.
-        self.broken_learning_object = LearningObject.objects.create(
+        cls.broken_learning_object = LearningObject.objects.create(
             name="test learning object",
-            course_module=self.course_module_with_late_submissions_allowed,
-            category=self.learning_object_category,
+            course_module=cls.course_module_with_late_submissions_allowed,
+            category=cls.learning_object_category,
             url="l2",
         )
 
-        self.base_exercise = BaseExercise.objects.create(
+        cls.base_exercise = BaseExercise.objects.create(
             order=1,
             name="test exercise",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url="b1",
             max_submissions=1,
         )
 
-        self.static_exercise = StaticExercise.objects.create(
+        cls.static_exercise = StaticExercise.objects.create(
             order=2,
             name="test exercise 2",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url="s2",
             max_points=50,
             points_to_pass=50,
@@ -164,11 +165,11 @@ def setUp(self): # pylint: disable=too-many-statements
             submission_page_content="test_submission_content"
         )
 
-        self.exercise_with_attachment = ExerciseWithAttachment.objects.create(
+        cls.exercise_with_attachment = ExerciseWithAttachment.objects.create(
             order=3,
             name="test exercise 3",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url="a1",
             max_points=50,
             points_to_pass=50,
@@ -177,88 +178,88 @@ def setUp(self): # pylint: disable=too-many-statements
             content="test_instructions"
         )
 
-        self.old_base_exercise = BaseExercise.objects.create(
+        cls.old_base_exercise = BaseExercise.objects.create(
             name="test exercise",
-            course_module=self.old_course_module,
-            category=self.learning_object_category,
+            course_module=cls.old_course_module,
+            category=cls.learning_object_category,
             url="b2",
             max_submissions=1
         )
 
-        self.exercise_in_reading_time = BaseExercise.objects.create(
+        cls.exercise_in_reading_time = BaseExercise.objects.create(
             order=1,
             name="test exercise",
-            course_module=self.reading_open_course_module,
-            category=self.learning_object_category,
+            course_module=cls.reading_open_course_module,
+            category=cls.learning_object_category,
             url="b1",
             max_submissions=1,
         )
 
-        self.base_exercise_with_late_submission_allowed = BaseExercise.objects.create(
+        cls.base_exercise_with_late_submission_allowed = BaseExercise.objects.create(
             name="test exercise with late submissions allowed",
-            course_module=self.course_module_with_late_submissions_allowed,
-            category=self.learning_object_category,
+            course_module=cls.course_module_with_late_submissions_allowed,
+            category=cls.learning_object_category,
             url="b3",
         )
 
-        self.enrollment_exercise = BaseExercise.objects.create(
+        cls.enrollment_exercise = BaseExercise.objects.create(
             name="test enrollment exercise",
-            course_module=self.old_course_module,
-            category=self.learning_object_category,
+            course_module=cls.old_course_module,
+            category=cls.learning_object_category,
             url="enroll-exercise",
             max_submissions=1,
             status="enrollment",
         )
 
-        self.submission = Submission.objects.create(
-            exercise=self.base_exercise,
-            grader=self.grader.userprofile
+        cls.submission = Submission.objects.create(
+            exercise=cls.base_exercise,
+            grader=cls.grader.userprofile
         )
-        self.submission.submitters.add(self.user.userprofile)
+        cls.submission.submitters.add(cls.user.userprofile)
 
-        self.submission_with_two_submitters = Submission.objects.create(
-            exercise=self.base_exercise,
-            grader=self.grader.userprofile
+        cls.submission_with_two_submitters = Submission.objects.create(
+            exercise=cls.base_exercise,
+            grader=cls.grader.userprofile
         )
-        self.submission_with_two_submitters.submitters.add(self.user.userprofile)
-        self.submission_with_two_submitters.submitters.add(self.user2.userprofile)
+        cls.submission_with_two_submitters.submitters.add(cls.user.userprofile)
+        cls.submission_with_two_submitters.submitters.add(cls.user2.userprofile)
 
-        self.late_submission = Submission.objects.create(
-            exercise=self.base_exercise,
-            grader=self.grader.userprofile
+        cls.late_submission = Submission.objects.create(
+            exercise=cls.base_exercise,
+            grader=cls.grader.userprofile
         )
-        self.late_submission.submission_time = self.two_days_from_now
-        self.late_submission.submitters.add(self.user.userprofile)
+        cls.late_submission.submission_time = cls.two_days_from_now
+        cls.late_submission.submitters.add(cls.user.userprofile)
 
-        self.submission_when_late_allowed = Submission.objects.create(
-            exercise=self.base_exercise_with_late_submission_allowed,
-            grader=self.grader.userprofile
+        cls.submission_when_late_allowed = Submission.objects.create(
+            exercise=cls.base_exercise_with_late_submission_allowed,
+            grader=cls.grader.userprofile
         )
-        self.submission_when_late_allowed.submitters.add(self.user.userprofile)
+        cls.submission_when_late_allowed.submitters.add(cls.user.userprofile)
 
-        self.late_submission_when_late_allowed = Submission.objects.create(
-            exercise=self.base_exercise_with_late_submission_allowed,
-            grader=self.grader.userprofile
+        cls.late_submission_when_late_allowed = Submission.objects.create(
+            exercise=cls.base_exercise_with_late_submission_allowed,
+            grader=cls.grader.userprofile
         )
-        self.late_submission_when_late_allowed.submission_time = self.two_days_from_now
-        self.late_submission_when_late_allowed.submitters.add(self.user.userprofile)
+        cls.late_submission_when_late_allowed.submission_time = cls.two_days_from_now
+        cls.late_submission_when_late_allowed.submitters.add(cls.user.userprofile)
 
-        self.late_late_submission_when_late_allowed = Submission.objects.create(
-            exercise=self.base_exercise_with_late_submission_allowed,
-            grader=self.grader.userprofile
+        cls.late_late_submission_when_late_allowed = Submission.objects.create(
+            exercise=cls.base_exercise_with_late_submission_allowed,
+            grader=cls.grader.userprofile
         )
-        self.late_late_submission_when_late_allowed.submission_time = self.three_days_from_now
-        self.late_late_submission_when_late_allowed.submitters.add(self.user.userprofile)
+        cls.late_late_submission_when_late_allowed.submission_time = cls.three_days_from_now
+        cls.late_late_submission_when_late_allowed.submitters.add(cls.user.userprofile)
 
-        self.course_hook = CourseHook.objects.create(
+        cls.course_hook = CourseHook.objects.create(
             hook_url="http://localhost/test_hook_url",
-            course_instance=self.course_instance
+            course_instance=cls.course_instance
         )
 
-        self.deadline_rule_deviation = DeadlineRuleDeviation.objects.create(
-            exercise=self.exercise_with_attachment,
-            submitter=self.user.userprofile,
-            granter=self.teacher.userprofile,
+        cls.deadline_rule_deviation = DeadlineRuleDeviation.objects.create(
+            exercise=cls.exercise_with_attachment,
+            submitter=cls.user.userprofile,
+            granter=cls.teacher.userprofile,
             extra_seconds=24*60*60  # One day
         )
 
diff --git a/external_services/tests.py b/external_services/tests.py
--- a/external_services/tests.py
+++ b/external_services/tests.py
@@ -10,28 +10,29 @@
 
 
 class ExternalServicesTest(TestCase):
-    def setUp(self):
-        self.user = User(username="testUser")
-        self.user.set_password("testPassword")
-        self.user.save()
+    @classmethod
+    def setUpTestData(cls):
+        cls.user = User(username="testUser")
+        cls.user.set_password("testPassword")
+        cls.user.save()
 
-        self.assistant = User(username="testUser2")
-        self.assistant.set_password("testPassword")
-        self.assistant.save()
+        cls.assistant = User(username="testUser2")
+        cls.assistant.set_password("testPassword")
+        cls.assistant.save()
 
-        self.link_service = LinkService.objects.create(
+        cls.link_service = LinkService.objects.create(
             url="http://www.external-service.com",
             destination_region=LinkService.DESTINATION_REGION.INTERNAL,
             menu_label="External Service"
         )
 
-        self.disabled_link_service = LinkService.objects.create(
+        cls.disabled_link_service = LinkService.objects.create(
             url="http://www.disabled-external-service.com",
             destination_region=LinkService.DESTINATION_REGION.INTERNAL,
             menu_label="Disabled External Service",
             enabled=False
         )
-        self.lti_service = LTIService.objects.create(
+        cls.lti_service = LTIService.objects.create(
             url="http://www.lti-service.com",
             destination_region=LinkService.DESTINATION_REGION.INTERNAL,
             menu_label="LTI Service",
@@ -41,55 +42,55 @@ def setUp(self):
             consumer_secret="987654321"
         )
 
-        self.course = Course.objects.create(
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
 
-        self.course_instance = CourseInstance.objects.create(
+        cls.course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_2011"
         )
-        self.course_instance.enroll_student(self.user)
-        self.course_instance.add_assistant(self.assistant.userprofile)
+        cls.course_instance.enroll_student(cls.user)
+        cls.course_instance.add_assistant(cls.assistant.userprofile)
 
-        self.menu_item1 = MenuItem.objects.create(
-            service=self.link_service,
-            course_instance=self.course_instance,
+        cls.menu_item1 = MenuItem.objects.create(
+            service=cls.link_service,
+            course_instance=cls.course_instance,
             access=MenuItem.ACCESS.STUDENT,
             menu_label="Overriden Label",
             menu_icon_class="star"
         )
 
-        self.menu_item2 = MenuItem.objects.create(
-            service=self.link_service,
-            course_instance=self.course_instance,
+        cls.menu_item2 = MenuItem.objects.create(
+            service=cls.link_service,
+            course_instance=cls.course_instance,
             access=MenuItem.ACCESS.STUDENT,
             enabled=False
         )
 
-        self.menu_item3 = MenuItem.objects.create(
-            service=self.disabled_link_service,
-            course_instance=self.course_instance,
+        cls.menu_item3 = MenuItem.objects.create(
+            service=cls.disabled_link_service,
+            course_instance=cls.course_instance,
             access=MenuItem.ACCESS.STUDENT
         )
 
-        self.menu_item4 = MenuItem.objects.create(
-            service=self.lti_service,
-            course_instance=self.course_instance,
+        cls.menu_item4 = MenuItem.objects.create(
+            service=cls.lti_service,
+            course_instance=cls.course_instance,
             access=MenuItem.ACCESS.STUDENT
         )
 
-        self.menu_item5 = MenuItem.objects.create(
-            service=self.lti_service,
-            course_instance=self.course_instance,
+        cls.menu_item5 = MenuItem.objects.create(
+            service=cls.lti_service,
+            course_instance=cls.course_instance,
             access=MenuItem.ACCESS.ASSISTANT
         )
 
diff --git a/redirect_old_urls/tests.py b/redirect_old_urls/tests.py
--- a/redirect_old_urls/tests.py
+++ b/redirect_old_urls/tests.py
@@ -10,43 +10,44 @@
 
 class RedirectTest(TestCase):
 
-    def setUp(self):
-        self.user = User(username="testUser")
-        self.user.set_password("testPassword")
-        self.user.save()
-        self.user.userprofile.student_id = '123456'
-        self.user.userprofile.organization = settings.LOCAL_ORGANIZATION
-        self.user.userprofile.save()
-        self.course = Course.objects.create(
+    @classmethod
+    def setUpTestData(cls):
+        cls.user = User(username="testUser")
+        cls.user.set_password("testPassword")
+        cls.user.save()
+        cls.user.userprofile.student_id = '123456'
+        cls.user.userprofile.organization = settings.LOCAL_ORGANIZATION
+        cls.user.userprofile.save()
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
-        self.course_instance = CourseInstance.objects.create(
+        cls.course_instance = CourseInstance.objects.create(
             instance_name="Fall 2011",
             starting_time=timezone.now(),
             ending_time=timezone.now() + timedelta(days=5),
-            course=self.course,
+            course=cls.course,
             url="T-00.1000_2011",
             view_content_to=CourseInstance.VIEW_ACCESS.ENROLLMENT_AUDIENCE,
         )
-        self.course_module = CourseModule.objects.create(
+        cls.course_module = CourseModule.objects.create(
             name="test module",
             url="test-module",
             points_to_pass=15,
-            course_instance=self.course_instance,
+            course_instance=cls.course_instance,
             opening_time=timezone.now(),
             closing_time=timezone.now() + timedelta(days=5)
         )
-        self.learning_object_category = LearningObjectCategory.objects.create(
+        cls.learning_object_category = LearningObjectCategory.objects.create(
             name="test category",
-            course_instance=self.course_instance,
+            course_instance=cls.course_instance,
             points_to_pass=5
         )
-        self.exercise = StaticExercise.objects.create(
+        cls.exercise = StaticExercise.objects.create(
             name="test exercise",
-            course_module=self.course_module,
-            category=self.learning_object_category,
+            course_module=cls.course_module,
+            category=cls.learning_object_category,
             url='e1',
         )
 
diff --git a/shibboleth_login/tests.py b/shibboleth_login/tests.py
--- a/shibboleth_login/tests.py
+++ b/shibboleth_login/tests.py
@@ -37,20 +37,21 @@
 @override_settings(SHIBBOLETH_ENVIRONMENT_VARS=ENV_VARS)
 class ShibbolethTest(TestCase):
 
-    def setUp(self):
-        self.user = User(
+    @classmethod
+    def setUpTestData(cls):
+        cls.user = User(
             username='meikalm8@first.invalid',
             email='matti@second.invalid',
             first_name='Matti',
             last_name='Sukunimi',
         )
-        self.user.set_unusable_password()
-        self.user.save()
-        self.user.userprofile.student_id = '000'
-        self.user.userprofile.organization = 'first.invalid'
-        self.user.userprofile.save()
+        cls.user.set_unusable_password()
+        cls.user.save()
+        cls.user.userprofile.student_id = '000'
+        cls.user.userprofile.organization = 'first.invalid'
+        cls.user.userprofile.save()
 
-        self.login_url = reverse('shibboleth-login')
+        cls.login_url = reverse('shibboleth-login')
 
     def test_permission_is_denied_when_user_id_is_missing(self):
         meta = DEF_SHIBD_META.copy()
diff --git a/threshold/tests.py b/threshold/tests.py
--- a/threshold/tests.py
+++ b/threshold/tests.py
@@ -45,11 +45,12 @@ class ThresholdTest(CourseTestCase):
         'points_by_difficulty':{'A':1700,'B':0,'C':1775}
     })
 
-    def setUp(self):
-        self.setUpCourse()
-        self.setUpSubmissions()
-        self.grades = list([ # pylint: disable=consider-using-generator
-            Threshold.objects.create(course_instance=self.instance, name=name)
+    @classmethod
+    def setUpTestData(cls):
+        cls.setUpCourse()
+        cls.setUpSubmissions()
+        cls.grades = list([ # pylint: disable=consider-using-generator
+            Threshold.objects.create(course_instance=cls.instance, name=name)
             for name in ["1", "2", "3", "4", "5"]
         ])
 
diff --git a/userprofile/api/tests.py b/userprofile/api/tests.py
--- a/userprofile/api/tests.py
+++ b/userprofile/api/tests.py
@@ -1,11 +1,9 @@
 from typing import Set
-from django.test import TestCase
 from rest_framework.test import APIClient
+from ..tests import UserProfileTestCase
 
-class UserProfileAPITest(TestCase):
+class UserProfileAPITest(UserProfileTestCase):
     # use same setUp as for normal tests
-    from ..tests import UserProfileTest # pylint: disable=import-outside-toplevel
-    setUp = UserProfileTest.setUp
 
     def test_get_userlist(self):
         """
diff --git a/userprofile/tests.py b/userprofile/tests.py
--- a/userprofile/tests.py
+++ b/userprofile/tests.py
@@ -9,50 +9,51 @@
 from exercise.models import LearningObjectCategory
 from userprofile.models import UserProfile
 
+class UserProfileTestCase(TestCase):
 
-class UserProfileTest(TestCase):
-    def setUp(self):
+    @classmethod
+    def setUpTestData(cls):
         # Set the user's id manually so that user.id is different than userprofile.id.
-        self.student = User(
+        cls.student = User(
             id=101,
             username="testUser",
             first_name="Superb",
             last_name="Student",
             email="test@aplus.com"
         )
-        self.student.set_password("testPassword")
-        self.student.save()
-        self.student_profile = self.student.userprofile
-        self.student_profile.student_id = "12345X"
-        self.student_profile.organization = settings.LOCAL_ORGANIZATION
-        self.student_profile.save()
-
-        self.grader = User(
+        cls.student.set_password("testPassword")
+        cls.student.save()
+        cls.student_profile = cls.student.userprofile
+        cls.student_profile.student_id = "12345X"
+        cls.student_profile.organization = settings.LOCAL_ORGANIZATION
+        cls.student_profile.save()
+
+        cls.grader = User(
             id=102,
             username="grader",
             first_name="Grumpy",
             last_name="Grader",
             email="grader@aplus.com"
         )
-        self.grader.set_password("graderPassword")
-        self.grader.save()
-        self.grader_profile = self.grader.userprofile
-        self.grader_profile.student_id = "67890Y"
-        self.grader_profile.organization = settings.LOCAL_ORGANIZATION
-        self.grader_profile.save()
-
-        self.teacher = User(
+        cls.grader.set_password("graderPassword")
+        cls.grader.save()
+        cls.grader_profile = cls.grader.userprofile
+        cls.grader_profile.student_id = "67890Y"
+        cls.grader_profile.organization = settings.LOCAL_ORGANIZATION
+        cls.grader_profile.save()
+
+        cls.teacher = User(
             id=103,
             username="teacher",
             first_name="Tedious",
             last_name="Teacher",
             email="teacher@aplus.com"
         )
-        self.teacher.set_password("teacherPassword")
-        self.teacher.save()
-        self.teacher_profile = self.teacher.userprofile
+        cls.teacher.set_password("teacherPassword")
+        cls.teacher.save()
+        cls.teacher_profile = cls.teacher.userprofile
 
-        self.superuser = User(
+        cls.superuser = User(
             id=104,
             username="superuser",
             first_name="Super",
@@ -60,57 +61,59 @@ def setUp(self):
             email="superuser@aplus.com",
             is_superuser=True
         )
-        self.superuser.set_password("superuserPassword")
-        self.superuser.save()
-        self.superuser_profile = self.superuser.userprofile
+        cls.superuser.set_password("superuserPassword")
+        cls.superuser.save()
+        cls.superuser_profile = cls.superuser.userprofile
 
-        self.course = Course.objects.create(
+        cls.course = Course.objects.create(
             name="test course",
             code="123456",
             url="Course-Url"
         )
 
-        self.today = timezone.now()
-        self.tomorrow = self.today + timedelta(days=1)
-        self.two_days_from_now = self.tomorrow + timedelta(days=1)
+        cls.today = timezone.now()
+        cls.tomorrow = cls.today + timedelta(days=1)
+        cls.two_days_from_now = cls.tomorrow + timedelta(days=1)
 
-        self.course_instance1 = CourseInstance.objects.create(
+        cls.course_instance1 = CourseInstance.objects.create(
             instance_name="Fall 2011 day 1",
-            starting_time=self.today,
-            ending_time=self.tomorrow,
-            course=self.course,
+            starting_time=cls.today,
+            ending_time=cls.tomorrow,
+            course=cls.course,
             url="T-00.1000_d1"
         )
-        self.course_instance1.add_teacher(self.teacher.userprofile)
-        self.course_instance1.add_assistant(self.grader.userprofile)
+        cls.course_instance1.add_teacher(cls.teacher.userprofile)
+        cls.course_instance1.add_assistant(cls.grader.userprofile)
 
-        self.course_instance2 = CourseInstance.objects.create(
+        cls.course_instance2 = CourseInstance.objects.create(
             instance_name="Fall 2011 day 2",
-            starting_time=self.tomorrow,
-            ending_time=self.two_days_from_now,
-            course=self.course,
+            starting_time=cls.tomorrow,
+            ending_time=cls.two_days_from_now,
+            course=cls.course,
             url="T-00.1000_d2"
         )
-        self.course_instance2.add_teacher(self.teacher.userprofile)
+        cls.course_instance2.add_teacher(cls.teacher.userprofile)
 
-        self.learning_object_category1 = LearningObjectCategory.objects.create(
+        cls.learning_object_category1 = LearningObjectCategory.objects.create(
             name="test category 1",
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
-        #self.learning_object_category1.hidden_to.add(self.student_profile)
-        #self.learning_object_category1.hidden_to.add(self.grader_profile)
+        #cls.learning_object_category1.hidden_to.add(cls.student_profile)
+        #cls.learning_object_category1.hidden_to.add(cls.grader_profile)
 
-        self.learning_object_category2 = LearningObjectCategory.objects.create(
+        cls.learning_object_category2 = LearningObjectCategory.objects.create(
             name="test category 2",
-            course_instance=self.course_instance1
+            course_instance=cls.course_instance1
         )
-        #self.learning_object_category2.hidden_to.add(self.student_profile)
+        #cls.learning_object_category2.hidden_to.add(cls.student_profile)
 
-        self.learning_object_category3 = LearningObjectCategory.objects.create(
+        cls.learning_object_category3 = LearningObjectCategory.objects.create(
             name="test category 3",
-            course_instance=self.course_instance2
+            course_instance=cls.course_instance2
         )
 
+class UserProfileTest(UserProfileTestCase):
+
     def test_user_id_not_equal_profile_id(self):
         self.assertEqual(self.student.id, 101)
         self.assertEqual(self.grader.id, 102)