diff --git a/program/tests/__init__.py b/program/tests/__init__.py
index eeef18a2d317dfa39aea5752ac257bc20d0e04bd..bcabb8e902ac5c924e89990891b2924bbc91e916 100644
--- a/program/tests/__init__.py
+++ b/program/tests/__init__.py
@@ -1,9 +1,13 @@
 import datetime
+from io import BytesIO
+
+from PIL import Image as PILImage
 
 from django.contrib.auth.models import User
+from django.core.files.uploadedfile import SimpleUploadedFile
 from django.utils.text import slugify
 from django.utils.timezone import now
-from program.models import Note, RRule, Schedule, Show, TimeSlot
+from program.models import Image, Note, RRule, Schedule, Show, TimeSlot
 
 
 class SteeringTestCaseMixin:
@@ -33,6 +37,27 @@ class UserMixin:
         )
 
 
+class ImageMixin:
+    @staticmethod
+    def _get_image_file(size=(400, 400), color=(255, 0, 0)) -> SimpleUploadedFile:
+        image_bytes = BytesIO()
+
+        PILImage.new(mode="RGB", size=size, color=color).save(image_bytes, format="png")
+
+        return SimpleUploadedFile("image.png", image_bytes.getvalue())
+
+    @staticmethod
+    def _create_image(
+        size=(400, 400), color=(255, 0, 0), alt_text="", credits="", owner=None
+    ) -> Image:
+        return Image.objects.create(
+            alt_text=alt_text,
+            credits=credits,
+            image=ImageMixin._get_image_file(size=size, color=color),
+            owner=owner,
+        )
+
+
 class ShowMixin:
     def _create_show(self, name: str, **kwargs):
         kwargs["name"] = name
diff --git a/program/tests/test_images.py b/program/tests/test_images.py
new file mode 100644
index 0000000000000000000000000000000000000000..7cf072d04f10cf5e46a5ed650d6b0246ce09c2d1
--- /dev/null
+++ b/program/tests/test_images.py
@@ -0,0 +1,135 @@
+from rest_framework.test import APITransactionTestCase
+
+from program.tests import ImageMixin, SteeringTestCaseMixin, UserMixin
+
+
+class ImageViewTestCase(UserMixin, ImageMixin, SteeringTestCaseMixin, APITransactionTestCase):
+    reset_sequences = True
+
+    def test_create_image(self):
+        client = self._get_client(self.user_admin)
+        url = self._url("images")
+        image_data = {"image": self._get_image_file()}
+
+        response = client.post(url, data=image_data, format="multipart")
+
+        self.assertEqual(response.status_code, 201)
+
+    def test_destroy_image(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_admin)
+        url = self._url("images", image.id)
+
+        response = client.delete(url)
+
+        self.assertEqual(response.status_code, 204)
+
+    def test_destroy_image_not_found_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_common)
+        url = self._url("images", image.id)
+
+        response = client.delete(url)
+
+        self.assertEqual(response.status_code, 404)
+
+    def test_list_images(self):
+        client = self._get_client(self.user_admin)
+        url = self._url("images")
+        for _ in range(3):
+            self._create_image(owner=self.user_admin)
+
+        response = client.get(url)
+
+        self.assertEqual(len(response.data), 3)
+
+    def test_list_images_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        url = self._url("images")
+        for _ in range(3):
+            self._create_image(owner=self.user_common)
+
+        response = client.get(url)
+
+        self.assertEqual(len(response.data), 0)
+
+    def test_retrieve_image(self):
+        client = self._get_client(self.user_admin)
+        data = {"alt_text": "ALT_TEXT", "credits": "CREDITS"}
+        image = self._create_image(**data, owner=self.user_admin)
+        url = self._url("images", image.id)
+
+        response = client.get(url)
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.data["alt_text"], data["alt_text"])
+        self.assertEqual(response.data["credits"], data["credits"])
+
+    def test_retrieve_image_not_found_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_common)
+        url = self._url("images", image.id)
+
+        response = client.get(url)
+
+        self.assertEqual(response.status_code, 404)
+
+    def test_update_alt_text(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_admin)
+        url = self._url("images", image.id)
+        update = {"alt_text": "ALT_TEXT"}
+
+        response = client.put(url, data=update)
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.data["alt_text"], update["alt_text"])
+
+    def test_update_alt_text_not_found_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_common)
+        url = self._url("images", image.id)
+
+        response = client.put(url, data={"alt_text": "ALT_TEXT"})
+
+        self.assertEqual(response.status_code, 404)
+
+    def test_update_credits(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_admin)
+        url = self._url("images", image.id)
+        update = {"credits": "CREDITS"}
+
+        response = client.put(url, data=update)
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.data["credits"], update["credits"])
+
+    def test_update_credits_not_found_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_common)
+        url = self._url("images", image.id)
+
+        response = client.put(url, data={"credits": "CREDITS"})
+
+        self.assertEqual(response.status_code, 404)
+
+    def test_update_ppoi(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_admin)
+        url = self._url("images", image.id)
+        update = {"ppoi": "0.3x0.7"}
+
+        response = client.put(url, data=update)
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.data["ppoi"], update["ppoi"])
+
+    def test_update_ppoi_not_found_for_different_user(self):
+        client = self._get_client(self.user_admin)
+        image = self._create_image(owner=self.user_common)
+        url = self._url("images", image.id)
+
+        response = client.put(url, data={"ppoi": "0.3x0.7"})
+
+        self.assertEqual(response.status_code, 404)