diff --git a/src/tests/scheduler/test-taskscheduler.cpp b/src/tests/scheduler/test-taskscheduler.cpp
index 1ac40adbd241aa0733b73f77cb30ab4c50d36e2f..bf842aa1f0db2459bde6148dd5dc667e1950f45e 100644
--- a/src/tests/scheduler/test-taskscheduler.cpp
+++ b/src/tests/scheduler/test-taskscheduler.cpp
@@ -22,6 +22,8 @@
 
 #include <scheduler/TaskScheduler.h>
 
+namespace
+{
 using namespace Boardcore;
 using namespace miosix;
 
@@ -31,13 +33,18 @@ GpioPin pin3 = GpioPin(GPIOB_BASE, 15);
 GpioPin pin4 = GpioPin(GPIOD_BASE, 8);
 GpioPin pin5 = GpioPin(GPIOD_BASE, 9);
 
+bool taskLogEnabled;  ///< A flag to enable/disable task logging
+
 void task2Hz()
 {
     pin1.high();
     delayUs(1);
     pin1.low();
 
-    printf("2 Hz tick\n");
+    if (taskLogEnabled)
+    {
+        printf("2 Hz tick\n");
+    }
 }
 
 void task5Hz()
@@ -45,6 +52,11 @@ void task5Hz()
     pin2.high();
     delayUs(1);
     pin2.low();
+
+    if (taskLogEnabled)
+    {
+        printf("5 Hz tick\n");
+    }
 }
 
 void task500Hz()
@@ -70,7 +82,17 @@ void signalPin5()
 
 void blockingTask() { delayMs(100); }
 
-int main()
+// Shared task functions between tests
+TaskScheduler::function_t f2Hz{&task2Hz};            ///< A 2 Hz task
+TaskScheduler::function_t f5Hz{&task5Hz};            ///< A 5 Hz task
+TaskScheduler::function_t f500Hz{&task500Hz};        ///< A 500 Hz task
+TaskScheduler::function_t f1KHz{&task1KHz};          ///< A 1 KHz task
+TaskScheduler::function_t blockingF{&blockingTask};  ///< A blocking task
+
+/**
+ * @brief Sets up the output pins
+ */
+void setup()
 {
     pin1.mode(Mode::OUTPUT);
     pin1.low();
@@ -83,17 +105,36 @@ int main()
     pin5.mode(Mode::OUTPUT);
     pin5.low();
 
-    TaskScheduler scheduler;
+    taskLogEnabled = true;
+}
 
-    TaskScheduler::function_t f2Hz{&task2Hz};
-    TaskScheduler::function_t f5Hz{&task5Hz};
-    TaskScheduler::function_t f500Hz{&task500Hz};
-    TaskScheduler::function_t f1KHz{&task1KHz};
-    TaskScheduler::function_t blockingF{&blockingTask};
+void printTaskStats(TaskScheduler& scheduler)
+{
+    printf("Tasks stats:\n");
+    for (auto stat : scheduler.getTaskStats())
+    {
+        printf("- %d:\n", stat.id);
+        printf("\tActivation: %.2f, %.2f\n", stat.activationStats.mean,
+               stat.activationStats.stdDev);
+        printf("\tPeriod: %.2f, %.2f\n", stat.periodStats.mean,
+               stat.periodStats.stdDev);
+        printf("\tWorkload: %.2f, %.2f\n", stat.workloadStats.mean,
+               stat.workloadStats.stdDev);
+        printf("\tMissed events: %ld\n", stat.missedEvents);
+        printf("\tFailed events: %ld\n", stat.failedEvents);
+    }
+}
 
-    scheduler.addTask(f2Hz, 500);
+/**
+ * @brief Tests the most common usage patters of the scheduler
+ */
+void test_general_purpose()
+{
+    TaskScheduler scheduler{};
+
+    int task1 = scheduler.addTask(f2Hz, 500);
     scheduler.addTask(f5Hz, 200);
-    scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+    int task3 = scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
     scheduler.addTask(f1KHz, 1, TaskScheduler::Policy::RECOVER);
     scheduler.addTask(f1KHz, 1, TaskScheduler::Policy::RECOVER);
 
@@ -106,26 +147,28 @@ int main()
     if (!scheduler.start())
     {
         printf("Error starting the task scheduler\n");
-        return 0;
+        return;
     }
 
     Thread::sleep(4 * 1000);
 
     signalPin5();
+    scheduler.disableTask(task1);
+    scheduler.disableTask(task3);
     printf("Removed tasks 1 (2Hz) and 3 (500Hz)\n");
 
     Thread::sleep(4 * 1000);
 
     printf("Now re-adding task 1 and 3\n");
     signalPin5();
-    scheduler.addTask(f2Hz, 500);
-    scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+    scheduler.enableTask(task1);
+    scheduler.enableTask(task3);
 
     Thread::sleep(4 * 1000);
 
     printf("Now adding a one shot task which will take 100ms to complete\n");
     signalPin5();
-    // scheduler.addTask(blockingF, 0, TaskScheduler::Policy::ONE_SHOT);
+    scheduler.addTask(blockingF, 0, TaskScheduler::Policy::ONE_SHOT);
 
     Thread::sleep(4 * 1000);
 
@@ -133,17 +176,237 @@ int main()
     scheduler.stop();
     printf("Task scheduler stopped\n");
 
-    printf("Tasks stats:\n");
-    for (auto stat : scheduler.getTaskStats())
+    printTaskStats(scheduler);
+}
+
+/**
+ * @brief Tests scheduler with a full task list
+ */
+void test_fill_scheduler()
+{
+    TaskScheduler scheduler{};
+
+    printf("Adding tasks until the scheduler is full\n");
+    size_t taskCount = 0;
+    // Fill up the scheduler with tasks
+    do
     {
-        printf("- %d:\n", stat.id);
-        printf("\tActivation: %.2f, %.2f\n", stat.activationStats.mean,
-               stat.activationStats.stdDev);
-        printf("\tPeriod: %.2f, %.2f\n", stat.periodStats.mean,
-               stat.periodStats.stdDev);
-        printf("\tWorkload: %.2f, %.2f\n", stat.workloadStats.mean,
-               stat.workloadStats.stdDev);
-        printf("\tMissed events: %lu\n", stat.missedEvents);
-        printf("\tFailed events: %lu\n", stat.failedEvents);
+        size_t lastId =
+            scheduler.addTask(f2Hz, 500, TaskScheduler::Policy::ONE_SHOT);
+        if (!lastId)
+        {
+            break;
+        }
+        taskCount++;
+    } while (true);
+
+    // Subtract one because the 0-th task is reserved
+    if (taskCount != TaskScheduler::MAX_TASKS - 1)
+    {
+        printf("Error: couldn't fill the scheduler: taskCount = %zu \n",
+               taskCount);
+        return;
+    }
+
+    printf("Done adding tasks: taskCount = %zu\n", taskCount);
+
+    printf("Trying to add another task\n");
+    // Try to add another task
+    if (scheduler.addTask(f2Hz, 500, TaskScheduler::Policy::ONE_SHOT))
+    {
+        printf("Error: added a task when the scheduler was full\n");
+        return;
+    }
+
+    printf("Added tasks successfully\n");
+
+    printf("Starting the scheduler\n");
+    scheduler.start();
+
+    Thread::sleep(4 * 1000);
+
+    printf("Stopping the scheduler\n");
+    scheduler.stop();
+
+    printTaskStats(scheduler);
+}
+
+/**
+ * @brief Tests the addTask function while the scheduler is running
+ */
+void test_runtime_add_task()
+{
+    TaskScheduler scheduler{};
+
+    scheduler.addTask(f2Hz, 500);
+    scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+
+    printf("2 tasks added (2Hz 500Hz)\n");
+    printf("Starting the scheduler\n");
+    scheduler.start();
+
+    Thread::sleep(4 * 1000);
+
+    printf("Adding a new task (5Hz)\n");
+    if (!scheduler.addTask(f5Hz, 200))
+    {
+        printf("Error adding task while the scheduler is running\n");
     }
+
+    Thread::sleep(4 * 1000);
+
+    printf("Stopping the scheduler\n");
+    scheduler.stop();
+}
+
+/**
+ * @brief Tests the enable/disable functions of the scheduler
+ */
+void test_enable_disable()
+{
+    TaskScheduler scheduler{};
+
+    int task1 = scheduler.addTask(f2Hz, 500);
+    scheduler.addTask(f5Hz, 200);
+    int task3 = scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+
+    printf("3 tasks added (2Hz 5Hz 500Hz)\n");
+    printf("Starting the scheduler\n");
+    scheduler.start();
+
+    Thread::sleep(4 * 1000);
+
+    printf("Disabling task 1 (2Hz) and 3 (500Hz)\n");
+    scheduler.disableTask(task1);
+    scheduler.disableTask(task3);
+
+    Thread::sleep(4 * 1000);
+
+    printf("Re-enabling task 1 (2Hz) and 3 (500Hz)\n");
+    scheduler.enableTask(task1);
+    scheduler.enableTask(task3);
+
+    printf("Disabling task 2 (5Hz)\n");
+
+    Thread::sleep(2 * 1000);
+
+    scheduler.stop();
+    printf("Task scheduler stopped\n");
+
+    printTaskStats(scheduler);
+}
+
+/**
+ * @brief Tests various edge cases of the scheduler:
+ * - Disabling out-of-range tasks
+ * - Enabling out-of-range tasks
+ * - Double start
+ */
+void test_edge_cases()
+{
+    TaskScheduler scheduler{};
+
+    scheduler.addTask(f2Hz, 500);
+    scheduler.addTask(f5Hz, 200);
+    scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+
+    printf("3 tasks added (2Hz 5Hz 500Hz)\n");
+    printf("Starting the scheduler\n");
+    scheduler.start();
+
+    printf("Starting the scheduler again");
+    if (scheduler.start())
+    {
+        printf("Error: started the scheduler twice\n");
+    }
+
+    Thread::sleep(1000);
+
+    printf("Disabling out-of-range tasks with IDs 0 and 256");
+    scheduler.disableTask(0);
+    scheduler.disableTask(256);
+
+    Thread::sleep(1000);
+
+    printf("Enabling out-of-range tasks with IDs 0 and 256");
+    scheduler.enableTask(0);
+    scheduler.enableTask(256);
+
+    Thread::sleep(1000);
+
+    printf("Stopping the scheduler\n");
+    scheduler.stop();
+}
+
+/**
+ * @brief Tests the scheduler with a general usage pattern for a prolonged
+ * period of time
+ */
+void test_long_range()
+{
+    TaskScheduler scheduler{};
+
+    scheduler.addTask(f2Hz, 500);
+    scheduler.addTask(f5Hz, 200);
+    scheduler.addTask(f500Hz, 2, TaskScheduler::Policy::RECOVER);
+
+    printf("3 tasks added (2Hz 5Hz 500Hz)\n");
+    printf("A message will be printed every minute\n");
+    printf("Starting the scheduler\n");
+    scheduler.start();
+
+    for (int i = 0; i < 5; i++)
+    {
+        printf("Scheduler running for %d minute(s)\n", i);
+        Thread::sleep(60 * 1000);
+    }
+
+    printf("Stopping the scheduler\n");
+    scheduler.stop();
+}
+
+}  // namespace
+
+int main()
+{
+    setup();
+
+    // Avoid clutter from tasks since this test will add a lot of tasks
+    taskLogEnabled = false;
+    printf("=> Running the fill scheduler test\n");
+    test_fill_scheduler();
+    taskLogEnabled = true;
+
+    printf("\n");
+
+    printf("=> Running the runtime add task test\n");
+    test_runtime_add_task();
+
+    printf("\n");
+
+    printf("=> Running the enable/disable test\n");
+    test_enable_disable();
+
+    printf("\n");
+
+    printf("=> Running the edge cases tests\n");
+    test_edge_cases();
+
+    printf("\n");
+
+    printf("=> Running the general purpose test\n");
+    test_general_purpose();
+
+    printf("\n");
+
+    // Avoid clutter from tasks since this test will run for a while
+    taskLogEnabled = false;
+    printf("=> Running the long range test, this may take a while\n");
+    test_long_range();
+    taskLogEnabled = true;
+
+    printf("\n");
+
+    printf("\n=> Task Scheduler tests completed\n");
+    return 0;
 }