diff --git a/backend/app/crud/tests.py b/backend/app/crud/tests.py
index c84cde2d594ec58ea9bd52acae09da18102abe8c..a3ff16dbc9829058b58fe82730882320202608dd 100644
--- a/backend/app/crud/tests.py
+++ b/backend/app/crud/tests.py
@@ -90,13 +90,44 @@ def remove_group_from_test_task(
 def create_group(
     db: Session, group: schemas.TestTaskGroupCreate
 ) -> models.TestTaskGroup:
-    db_group = models.TestTaskGroup(**group.model_dump())
+    db_group = models.TestTaskGroup(
+        **group.model_dump(exclude_unset=True, exclude={"questions"})
+    )
+
+    if group.questions:
+        db_group.questions = (
+            db.query(models.TestTaskQuestion)
+            .filter(models.TestTaskQuestion.id.in_(group.questions))
+            .all()
+        )
     db.add(db_group)
     db.commit()
     db.refresh(db_group)
     return db_group
 
 
+def update_group(
+    db: Session, group: schemas.TestTaskGroupCreate, group_id: int
+) -> None:
+    current = db.query(models.TestTaskGroup).filter(models.TestTaskGroup.id == group_id)
+    current.update(
+        {
+            **group.model_dump(exclude_unset=True, exclude={"questions"}),
+        }
+    )
+
+    first = current.first()
+
+    if first:
+        first.questions = (
+            db.query(models.TestTaskQuestion)
+            .filter(models.TestTaskQuestion.id.in_(group.questions))
+            .all()
+        )
+
+    db.commit()
+
+
 def get_group(db: Session, group_id: int) -> models.TestTaskGroup | None:
     return (
         db.query(models.TestTaskGroup)
diff --git a/backend/app/routes/tests.py b/backend/app/routes/tests.py
index a8c7c13750dff17402d59517c9a171b76c9ac706..15db5c490b70448dbf1e8eb7a661eea918ce93e7 100644
--- a/backend/app/routes/tests.py
+++ b/backend/app/routes/tests.py
@@ -49,6 +49,35 @@ def get_groups(
     return crud.get_groups(db)
 
 
+@require_admin("You do not have permission to get a group.")
+@testRouter.get("/groups/{group_id}", response_model=schemas.TestTaskGroup)
+def get_group(
+    group_id: int,
+    db: Session = Depends(get_db),
+):
+    group = crud.get_group(db, group_id)
+    if group is None:
+        raise HTTPException(
+            status_code=status.HTTP_404_NOT_FOUND, detail="Group not found"
+        )
+    return group
+
+
+@require_admin("You do not have permission to edit a group.")
+@testRouter.put("/groups/{group_id}", status_code=status.HTTP_204_NO_CONTENT)
+def update_group(
+    group_id: int,
+    group: schemas.TestTaskGroupCreate,
+    db: Session = Depends(get_db),
+):
+    db_group = crud.get_group(db, group_id)
+    if db_group is None:
+        raise HTTPException(
+            status_code=status.HTTP_404_NOT_FOUND, detail="Group not found"
+        )
+    crud.update_group(db, group, group_id)
+
+
 @require_admin("You do not have permission to get all the questions.")
 @testRouter.get("/questions", response_model=list[schemas.TestTaskQuestion])
 def get_questions(
diff --git a/backend/app/schemas/tests.py b/backend/app/schemas/tests.py
index 41ea6af57544bbb2fcb47bcc086752270c95dfdb..2b92fe1411b1028a6f3a4647851791fec257bccc 100644
--- a/backend/app/schemas/tests.py
+++ b/backend/app/schemas/tests.py
@@ -65,6 +65,7 @@ class TestTaskGroupCreate(BaseModel):
     title: str
     demo: bool = False
     randomize: bool = True
+    questions: list[int] = []
 
 
 class TestTypingCreate(BaseModel):
@@ -74,8 +75,11 @@ class TestTypingCreate(BaseModel):
     duration: int | None = None
 
 
-class TestTaskGroup(TestTaskGroupCreate):
-    # id: int
+class TestTaskGroup(BaseModel):
+    id: int | None = None
+    title: str
+    demo: bool = False
+    randomize: bool = True
     questions: list[TestTaskQuestion] = []
 
 
diff --git a/frontend/src/lib/api/tests.ts b/frontend/src/lib/api/tests.ts
index 1f4b2e8d1a9b75c21a11f3446f650f756c077e97..6bdd3ef24bc7c055517b93c645fec4518933416b 100644
--- a/frontend/src/lib/api/tests.ts
+++ b/frontend/src/lib/api/tests.ts
@@ -195,6 +195,13 @@ export async function getTestGroupsAPI(fetch: fetchType): Promise<any> {
 	return groups;
 }
 
+export async function getTestTaskGroupAPI(fetch: fetchType, id: number): Promise<any> {
+	const response = await fetch(`/api/tests/groups/${id}`);
+	if (!response.ok) return null;
+	const group = await response.json();
+	return group;
+}
+
 export async function getTestQuestionsAPI(fetch: fetchType): Promise<any> {
 	const response = await fetch(`/api/tests/questions`);
 	if (!response.ok) return null;
@@ -240,3 +247,46 @@ export async function updateTestTaskAPI(
 	});
 	return response.ok;
 }
+
+export async function createTestTaskGroupAPI(
+	fetch: fetchType,
+	title: string,
+	demo: boolean,
+	randomize: boolean,
+	questions: number[]
+): Promise<number | null> {
+	const response = await fetch(`/api/tests/groups`, {
+		method: 'POST',
+		headers: { 'Content-Type': 'application/json' },
+		body: JSON.stringify({
+			title,
+			demo,
+			randomize,
+			questions
+		})
+	});
+	if (!response.ok) return null;
+	const group = await response.json();
+	return group.id;
+}
+
+export async function updateTestTaskGroupAPI(
+	fetch: fetchType,
+	id: number,
+	title: string,
+	demo: boolean,
+	randomize: boolean,
+	questions: number[]
+): Promise<boolean> {
+	const response = await fetch(`/api/tests/groups/${id}`, {
+		method: 'PUT',
+		headers: { 'Content-Type': 'application/json' },
+		body: JSON.stringify({
+			title,
+			demo,
+			randomize,
+			questions
+		})
+	});
+	return response.ok;
+}
diff --git a/frontend/src/routes/admin/tests/+page.svelte b/frontend/src/routes/admin/tests/+page.svelte
index 117b2364d0765181caecf653b0990867d96174a9..ca7147d00e5ea52bf5939ac62c64764d7d799de5 100644
--- a/frontend/src/routes/admin/tests/+page.svelte
+++ b/frontend/src/routes/admin/tests/+page.svelte
@@ -31,7 +31,7 @@
 		{/each}
 	</tbody>
 </table>
-<div class="mt-8 mx-auto w-[64rem] flex justify-between">
+<div class="mt-8 mx-auto w-[64rem] flex justify-between pb-8">
 	<a class="button" href="/admin/tests/new">{$t('tests.create')}</a>
 	<span>
 		<a class="btn" href="/admin/studies">⏎ {$t('tests.backtostudies')}</a>
diff --git a/frontend/src/routes/admin/tests/groups/+page.svelte b/frontend/src/routes/admin/tests/groups/+page.svelte
index b1b79de37821cf205a2722de992f2c8bb32b6b93..eaf8322fb72635ada4cb2c3b54b031bde116e6ce 100644
--- a/frontend/src/routes/admin/tests/groups/+page.svelte
+++ b/frontend/src/routes/admin/tests/groups/+page.svelte
@@ -35,7 +35,7 @@
 		{/each}
 	</tbody>
 </table>
-<div class="mt-8 mx-auto w-[64rem] flex justify-between">
+<div class="mt-8 mx-auto w-[64rem] flex justify-between pb-8">
 	<a class="button" href="/admin/tests/groups/new">{$t('tests.groups.create')}</a>
 	<span>
 		<a class="btn" href="/admin/tests">⏎ {$t('tests.groups.backtotests')}</a>
diff --git a/frontend/src/routes/admin/tests/groups/[id]/+page.server.ts b/frontend/src/routes/admin/tests/groups/[id]/+page.server.ts
index 5ecbb67f23bc3139a80d8d2a2cfb3eede42a23a7..ec22d98a967220e474347ccd7ad6e0bd71bfb4bb 100644
--- a/frontend/src/routes/admin/tests/groups/[id]/+page.server.ts
+++ b/frontend/src/routes/admin/tests/groups/[id]/+page.server.ts
@@ -1,5 +1,5 @@
 import { redirect, type Actions } from '@sveltejs/kit';
-import { updateTestTypingAPI } from '$lib/api/tests';
+import { updateTestTaskGroupAPI } from '$lib/api/tests';
 
 export const actions: Actions = {
 	default: async ({ request, fetch }) => {
@@ -7,9 +7,10 @@ export const actions: Actions = {
 
 		const idStr = formData.get('id')?.toString();
 		const title = formData.get('title')?.toString();
-		const type = formData.get('type')?.toString();
+		const demo = formData.get('demo')?.toString() == 'on';
+		const randomize = formData.get('randomize')?.toString() == 'on';
 
-		if (!title || !type || !idStr || (type !== 'typing' && type !== 'task')) {
+		if (!idStr || !title) {
 			return {
 				message: 'Invalid request: Missing required fields'
 			};
@@ -23,36 +24,19 @@ export const actions: Actions = {
 			};
 		}
 
-		if (type === 'typing') {
-			const explanation = formData.get('explanation')?.toString();
-			const text = formData.get('text')?.toString();
-			const repeatStr = formData.get('repeat')?.toString();
-			const durationStr = formData.get('duration')?.toString();
+		const questions = formData
+			.getAll('questions[]')
+			.map((question) => parseInt(question.toString(), 10))
+			.filter((question) => !isNaN(question));
 
-			if (!explanation || !text || !repeatStr || !durationStr) {
-				return {
-					message: 'Invalid request: Missing required fields'
-				};
-			}
+		const ok = await updateTestTaskGroupAPI(fetch, id, title, demo, randomize, questions);
 
-			const repeat = parseInt(repeatStr, 10);
-			const duration = parseInt(durationStr, 10);
-
-			if (isNaN(repeat) || isNaN(duration)) {
-				return {
-					message: 'Invalid request: Invalid format for numbers'
-				};
-			}
-
-			const ok = await updateTestTypingAPI(fetch, id, title, explanation, text, repeat, duration);
-
-			if (!ok) {
-				return {
-					message: 'Invalid request: Failed to update test'
-				};
-			}
-
-			return redirect(303, `/admin/tests`);
+		if (!ok) {
+			return {
+				message: 'Error updating test task group'
+			};
 		}
+
+		return redirect(303, `/admin/tests/groups`);
 	}
 };
diff --git a/frontend/src/routes/admin/tests/groups/[id]/+page.svelte b/frontend/src/routes/admin/tests/groups/[id]/+page.svelte
index 97ba7436319082212d3affbc96851cfd510d15bb..f2e0a43c4e4ef8841005d5cb25f11ebe7aec5d37 100644
--- a/frontend/src/routes/admin/tests/groups/[id]/+page.svelte
+++ b/frontend/src/routes/admin/tests/groups/[id]/+page.svelte
@@ -1,9 +1,9 @@
 <script lang="ts">
-	import TestForm from '$lib/components/tests/TestForm.svelte';
+	import GroupForm from '$lib/components/tests/GroupForm.svelte';
 	import type { PageData } from './$types';
 
-	const { data }: { data: PageData } = $props();
-	const { test, possibleGroups } = data;
+	const { data, form }: { data: PageData; form: FormData } = $props();
+	const { group, possibleQuestions } = data;
 </script>
 
-<TestForm {test} {possibleGroups} />
+<GroupForm {group} {possibleQuestions} message={form?.message} />
diff --git a/frontend/src/routes/admin/tests/groups/[id]/+page.ts b/frontend/src/routes/admin/tests/groups/[id]/+page.ts
index c49f9ecbdebc98feff80f8cb59ee5c82d38e1f90..e33e6f88c12a8126f04455b8f3e0b815ee0b0ac1 100644
--- a/frontend/src/routes/admin/tests/groups/[id]/+page.ts
+++ b/frontend/src/routes/admin/tests/groups/[id]/+page.ts
@@ -1,20 +1,31 @@
-import { getTestAPI, getTestGroupsAPI } from '$lib/api/tests';
-import { Test } from '$lib/types/tests';
+import { getTestQuestionsAPI, getTestTaskGroupAPI } from '$lib/api/tests';
 import TestTaskGroup from '$lib/types/testTaskGroups';
+import { TestTaskQuestion } from '$lib/types/testTaskQuestions';
 import { error, type Load } from '@sveltejs/kit';
 
 export const load: Load = async ({ fetch, params }) => {
-	const id = Number(params.id);
+	const idStr = params?.id;
+
+	if (!idStr) {
+		return error(400, 'Invalid ID');
+	}
+
+	const id = parseInt(idStr, 10);
 
 	if (isNaN(id)) {
 		return error(400, 'Invalid ID');
 	}
 
-	const testRaw = await getTestAPI(fetch, id);
-	const test = Test.parse(testRaw);
+	const groupRaw = await getTestTaskGroupAPI(fetch, id);
+
+	if (!groupRaw) {
+		return error(404, 'Group not found');
+	}
+
+	const group = TestTaskGroup.parse(groupRaw);
 
-	const groupsRaw = await getTestGroupsAPI(fetch);
-	const groups = TestTaskGroup.parseAll(groupsRaw);
+	const questionsRaw = await getTestQuestionsAPI(fetch);
+	const questions = TestTaskQuestion.parseAll(questionsRaw);
 
-	return { test, possibleGroups: groups };
+	return { group, possibleQuestions: questions };
 };
diff --git a/frontend/src/routes/admin/tests/groups/new/+page.server.ts b/frontend/src/routes/admin/tests/groups/new/+page.server.ts
index 2fe5e2218cd89c20a8fac9bfa9c8eec46bd4e196..fd54c87ab26d19ce43b697a5ffefc8c4321ffc90 100644
--- a/frontend/src/routes/admin/tests/groups/new/+page.server.ts
+++ b/frontend/src/routes/admin/tests/groups/new/+page.server.ts
@@ -1,5 +1,5 @@
 import { redirect, type Actions } from '@sveltejs/kit';
-import { createTestTypingAPI } from '$lib/api/tests';
+import { createTestTaskGroupAPI } from '$lib/api/tests';
 
 export const actions: Actions = {
 	default: async ({ request, fetch }) => {
@@ -9,7 +9,7 @@ export const actions: Actions = {
 		const demo = formData.get('demo')?.toString() == 'on';
 		const randomize = formData.get('randomize')?.toString() == 'on';
 
-		if (!title || !demo || !randomize) {
+		if (!title) {
 			return {
 				message: 'Invalid request: Missing required fields'
 			};
@@ -22,6 +22,12 @@ export const actions: Actions = {
 
 		const id = await createTestTaskGroupAPI(fetch, title, demo, randomize, questions);
 
-		return redirect(303, `/admin/tests`);
+		if (id === null) {
+			return {
+				message: 'Error creating test task group'
+			};
+		}
+
+		return redirect(303, `/admin/tests/groups`);
 	}
 };