diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ea2c233c937df57681ed297b88eb29b75d336893..09f4f73b2ad8df1b89b7de8b317cf2399707fe5d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ stages:
 doxec_unittest:
   stage: test
   script:
-    - python3 -m unittest doxec.tests
+    - python3 -m unittest -v doxec.tests
 
      
 doxec_doctest:
diff --git a/doxec/__init__.py b/doxec/__init__.py
index 301bb25e4ceb819a96018f4c6c1d6c3757d778a9..7ef09e5bc9cf945559b1f04fb8ab0f4945934fc5 100644
--- a/doxec/__init__.py
+++ b/doxec/__init__.py
@@ -94,6 +94,7 @@ class OpConsole(Operation):
         if job.returncode != 0:
             raise TestException("Script failed with %d:" % job.returncode,
                 stdoutdata.decode('utf8'), stderrdata.decode('utf8'))
+        return stdoutdata
                 
 
 
@@ -105,7 +106,30 @@ class OpConsoleOutput(Operation):
     command = "console_output"
 
     def execute(self):
-        pass
+        commands = []  # items are (command, [output lines])
+        for line in self.content:
+            if line.startswith("$"):
+                commands.append((line[1:], []))
+            elif len(commands) == 0:
+                # no command yet
+                continue
+            else:
+                commands[-1][1].append(line)
+
+        for command, lines in commands:
+            job = subprocess.Popen("/bin/bash", stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            (stdoutdata, stderrdata) = job.communicate(command.encode('utf8'))
+            if job.returncode != 0:
+                raise TestException("Script failed with %d:" % job.returncode,
+                    stdoutdata.decode('utf8'), stderrdata.decode('utf8'))
+            output = stdoutdata.decode('utf8')
+            output = re.split(r'\r?\n', output)
+            if len(output) > 0 and output[-1] == '':
+                del output[-1] 
+            if lines != output:
+                raise TestException("Output differs", lines, output)
+       
 
 # add operations to op_store
 Operation.op_store.append(OpConsole)
diff --git a/doxec/tests/operation.py b/doxec/tests/operation.py
index 3f31c185dc9c3cea5baeafd301599ecba5e5f07f..c1fa108b80c60683daa6ec2b38e823d0d114efac 100644
--- a/doxec/tests/operation.py
+++ b/doxec/tests/operation.py
@@ -169,4 +169,29 @@ class OpConsoleOutputTestCase(unittest.TestCase):
     Test the functionality of the console-output-operation. This test case focuses on
     the execute method.
     """
-    pass
+    
+    def test_execute_pass(self):
+        """
+        Creates an OpConsoleOutput operation and checks that no exception is raised,
+        when the expected output matches the actual output.
+        """
+        console = OpConsoleOutput(None,
+            ["$ echo 'Hi'", "Hi", "$ echo 'Hello\n  World'", "Hello", "  World"])
+        console.execute()
+
+    def test_execute_fail(self):
+        """
+        Creates an OpConsoleOutput operation and checks that an exception is raised,
+        when the expected output does not match the actual output.
+        """
+        console = OpConsoleOutput(None,
+            ["$ echo 'Hi'", "Hi", "$ echo 'Hello\n  World'", "Hello", "Moon"])
+        self.assertRaises(TestException, console.execute)
+
+    def test_execute_leading_comments(self):
+        """
+        Creates an OpConsoleOutput operation and checks whether leading
+        non-code lines are ignored.
+        """
+        console = OpConsoleOutput(None, ["heyho", "$ echo 'Hi'", "Hi"])
+        console.execute()