diff --git a/tests/gnrc_rpl_srh/Makefile b/tests/gnrc_rpl_srh/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1231460471f8e2ed62f87cb4ea5da71a32cb097a
--- /dev/null
+++ b/tests/gnrc_rpl_srh/Makefile
@@ -0,0 +1,56 @@
+DEVELHELP := 1
+# name of your application
+include ../Makefile.tests_common
+
+BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \
+                             hifive1 mega-xplained msb-430 msb-430h \
+                             nucleo-f030r8 nucleo-f031k6 nucleo-f042k6 \
+                             nucleo-f070rb nucleo-f072rb nucleo-f303k8 \
+                             nucleo-f334r8 nucleo-l031k6 nucleo-l053r8 \
+                             stm32f0discovery telosb thingy52 waspmote-pro \
+                             wsn430-v1_3b wsn430-v1_4 z1
+# chronos, mips-malta, and ruuvitag boards don't support ethos
+BOARD_BLACKLIST := chronos mips-malta ruuvitag
+
+export TAP ?= tap0
+
+CFLAGS += -DOUTPUT=TEXT
+
+# use Ethernet as link-layer protocol
+ifeq (native,$(BOARD))
+  USEMODULE += netdev_tap
+
+  TERMFLAGS ?= $(TAP)
+else
+  USEMODULE += ethos
+
+  ETHOS_BAUDRATE ?= 115200
+  CFLAGS += -DETHOS_BAUDRATE=$(ETHOS_BAUDRATE) -DUSE_ETHOS_FOR_STDIO
+  TERMDEPS += ethos
+  TERMPROG ?= sudo $(RIOTTOOLS)/ethos/ethos
+  TERMFLAGS ?= $(TAP) $(PORT) $(ETHOS_BAUDRATE)
+endif
+USEMODULE += auto_init_gnrc_netif
+# Specify the mandatory networking modules for IPv6
+USEMODULE += gnrc_ipv6_router_default
+USEMODULE += gnrc_icmpv6_error
+USEMODULE += gnrc_pktdump
+USEMODULE += gnrc_pktbuf_cmd
+# IPv6 extension headers
+USEMODULE += gnrc_rpl_srh
+USEMODULE += od
+# Add unittest framework
+USEMODULE += embunit
+# Add also the shell, some shell commands
+USEMODULE += shell
+USEMODULE += shell_commands
+USEMODULE += ps
+
+# TEST_ON_CI_WHITELIST += all
+
+.PHONY: ethos
+
+ethos:
+	$(Q)env -u CC -u CFLAGS make -C $(RIOTTOOLS)/ethos
+
+include $(RIOTBASE)/Makefile.include
diff --git a/tests/gnrc_rpl_srh/README.md b/tests/gnrc_rpl_srh/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3e1e5b65b879ac8e30795dc9cea560fafcc5853
--- /dev/null
+++ b/tests/gnrc_rpl_srh/README.md
@@ -0,0 +1,34 @@
+# `gnrc_ipv6_ext` test
+
+This test utilizes [scapy] to test the GNRC's RPL source routing header
+handling.
+
+To test, compile and flash the application to any board of your liking (since
+`ethos` is used to communicate with non-native boards it really doesn't matter
+as long as the application fits).
+
+```
+make flash
+```
+
+And run the tests using
+
+```
+sudo make test
+```
+
+Note that root privileges are required since `scapy` needs to construct Ethernet
+frames to properly communicate over the TAP interface.
+
+The tests succeeds if you see the string `SUCCESS`.
+
+If any problems are encountered (i.e. if the test prints the sting `FAILED`),
+set the echo parameter in the `run()` function at the bottom of the test script
+(tests/01-run.py) to `True`. The test script will then offer a more detailed
+output.
+
+It might be that due to `scapy`'s sniffer not picking up an expected packet
+sometimes that the test application hangs for a while and then issues `FAILED`.
+Just restart the test in that case.
+
+[scapy]: https://scapy.readthedocs.io/en/latest/
diff --git a/tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.c b/tests/gnrc_rpl_srh/main.c
similarity index 75%
rename from tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.c
rename to tests/gnrc_rpl_srh/main.c
index 6122c43937057de3d4c7ef291e0da3c49d3b5e94..26bb43adba089a108715b34858df5e1bd2594fa5 100644
--- a/tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.c
+++ b/tests/gnrc_rpl_srh/main.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
- * Copyright (C) 2018 Freie Universität Berlin
+ * Copyright (C) 2015 Freie Universität Berlin
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -8,25 +7,33 @@
  */
 
 /**
+ * @ingroup     tests
  * @{
  *
  * @file
- * @author Cenk Gündoğan <mail@cgundogan.de>
- * @author Martine Lenders <m.lenders@fu-berlin.de>
+ * @brief       Tests extension header handling of gnrc stack.
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ * @author      Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
+ *
+ * @}
  */
+
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
-#include "embUnit.h"
 
+#include "embUnit.h"
+#include "shell.h"
 #include "net/ipv6/addr.h"
 #include "net/ipv6/ext.h"
 #include "net/ipv6/hdr.h"
+#include "net/gnrc/pktbuf.h"
+#include "net/gnrc/pktdump.h"
+#include "net/gnrc/netreg.h"
 #include "net/gnrc/rpl/srh.h"
 #include "net/gnrc/ipv6/ext/rh.h"
 
-#include "unittests-constants.h"
-#include "tests-gnrc_rpl_srh.h"
-
 #define IPV6_DST            {{ 0x20, 0x01, 0xab, 0xcd, \
                                0x00, 0x00, 0x00, 0x00, \
                                0x00, 0x00, 0x00, 0x00, \
@@ -53,8 +60,12 @@
 
 static ipv6_hdr_t hdr;
 static uint8_t buf[MAX_BUF_SIZE];
+static char line_buf[SHELL_DEFAULT_BUFSIZE];
+static gnrc_netreg_entry_t ip_entry = GNRC_NETREG_ENTRY_INIT_PID(
+        0, KERNEL_PID_UNDEF
+    );
 
-static void set_up(void)
+static void set_up_tests(void)
 {
     memset(&hdr, 0, sizeof(hdr));
     memset(buf, 0, sizeof(buf));
@@ -188,7 +199,47 @@ static void test_rpl_srh_nexthop_prefix_elided(void)
     TEST_ASSERT(ipv6_addr_equal(&hdr.dst, &expected2));
 }
 
-static Test *tests_rpl_srh_tests(void)
+/* tools for external interaction */
+static inline void _ipreg_usage(char *cmd)
+{
+    printf("Usage: %s {reg|unreg}", cmd);
+}
+
+static int _ipreg(int argc, char **argv)
+{
+    if (argc < 2) {
+        _ipreg_usage(argv[0]);
+        return 1;
+    }
+    else if (strcmp("reg", argv[1]) == 0) {
+        if (ip_entry.target.pid != KERNEL_PID_UNDEF) {
+            puts("Already registered to protocol number 59");
+            return 1;
+        }
+        gnrc_netreg_entry_init_pid(&ip_entry, PROTNUM_IPV6_NONXT,
+                                   gnrc_pktdump_pid);
+        gnrc_netreg_register(GNRC_NETTYPE_IPV6, &ip_entry);
+        puts("Registered to protocol number 59");
+    }
+    else if (strcmp("unreg", argv[1]) == 0) {
+        puts("Unregistered from protocol number 59");
+        gnrc_netreg_unregister(GNRC_NETTYPE_IPV6, &ip_entry);
+        gnrc_netreg_entry_init_pid(&ip_entry, 0, KERNEL_PID_UNDEF);
+    }
+    else {
+        _ipreg_usage(argv[0]);
+        return 1;
+    }
+
+    return 0;
+}
+
+static const shell_command_t shell_commands[] = {
+    { "ip", "Registers pktdump to protocol number 59 (no next header)", _ipreg },
+    { NULL, NULL, NULL }
+};
+
+static void run_unittests(void)
 {
     EMB_UNIT_TESTFIXTURES(fixtures) {
         new_TestFixture(test_rpl_srh_dst_multicast),
@@ -198,13 +249,15 @@ static Test *tests_rpl_srh_tests(void)
         new_TestFixture(test_rpl_srh_nexthop_prefix_elided),
     };
 
-    EMB_UNIT_TESTCALLER(rpl_srh_tests, set_up, NULL, fixtures);
-
-    return (Test *)&rpl_srh_tests;
+    EMB_UNIT_TESTCALLER(rpl_srh_tests, set_up_tests, NULL, fixtures);
+    TESTS_START();
+    TESTS_RUN((Test *)&rpl_srh_tests);
+    TESTS_END();
 }
 
-void tests_gnrc_rpl_srh(void)
+int main(void)
 {
-    TESTS_RUN(tests_rpl_srh_tests());
+    run_unittests();
+    shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
+    return 0;
 }
-/** @} */
diff --git a/tests/gnrc_rpl_srh/tests/01-run.py b/tests/gnrc_rpl_srh/tests/01-run.py
new file mode 100755
index 0000000000000000000000000000000000000000..c86d7ca0a0bded3c82a5ee09349ffcf1be0826d4
--- /dev/null
+++ b/tests/gnrc_rpl_srh/tests/01-run.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 Freie Universität Berlin
+#
+# This file is subject to the terms and conditions of the GNU Lesser
+# General Public License v2.1. See the file LICENSE in the top level
+# directory for more details.
+
+import os
+import random
+import re
+import sys
+import subprocess
+import threading
+
+from scapy.all import Ether, IPv6, \
+                      IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, \
+                      IPv6ExtHdrFragment, IPv6ExtHdrRouting, \
+                      ICMPv6ParamProblem, ICMPv6TimeExceeded, \
+                      sendp, srp1, sniff
+from testrunner import run
+
+
+EXT_HDR_NH = {
+    IPv6ExtHdrHopByHop: 0,
+    IPv6ExtHdrRouting: 43,
+    IPv6ExtHdrFragment: 44,
+    # IPSec headers currently unsupported by scapy
+    IPv6ExtHdrDestOpt: 60,
+    # Mobility header currently unsupported by scapy
+  }
+
+
+class Sniffer(threading.Thread):
+    def __init__(self, iface, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.stop_filter = None
+        self.stopped = False
+        self.iface = iface
+        self.ps = []
+        self.enter_loop = threading.Event()
+        self.sniff_results = threading.Event()
+
+    def run(self):
+        while True:
+            self.enter_loop.wait()
+            self.enter_loop.clear()
+            if self.stopped:
+                return
+            if self.stop_filter:
+                self.ps = sniff(stop_filter=self.stop_filter,
+                                iface=self.iface, timeout=5)
+                self.stop_filter = None
+                self.sniff_results.set()
+
+    def start_sniff(self, stop_filter):
+        self.stop_filter = stop_filter
+        self.enter_loop.set()
+
+    def wait_for_sniff_results(self):
+        res = []
+        if self.sniff_results.wait(5):
+            self.sniff_results.clear()
+            res = self.ps
+        self.ps = []
+        return res
+
+    def stop(self):
+        self.stopped = True
+        self.enter_loop.set()
+        self.join()
+
+
+sniffer = None
+
+
+def check_and_search_output(cmd, pattern, res_group, *args, **kwargs):
+    output = subprocess.check_output(cmd, *args, **kwargs).decode("utf-8")
+    for line in output.splitlines():
+        m = re.search(pattern, line)
+        if m is not None:
+            return m.group(res_group)
+    return None
+
+
+def get_bridge(tap):
+    res = check_and_search_output(
+            ["bridge", "link"],
+            r"{}.+master\s+(?P<master>[^\s]+)".format(tap),
+            "master"
+        )
+    return tap if res is None else res
+
+
+def get_host_lladdr(tap):
+    res = check_and_search_output(
+            ["ip", "addr", "show", "dev", tap, "scope", "link"],
+            r"inet6\s+(?P<lladdr>[0-9A-Fa-f:]+)/\d+",
+            "lladdr"
+        )
+    if res is None:
+        raise AssertionError(
+                "Can't find host link-local address on interface {}".format(tap)
+            )
+    else:
+        return res
+
+
+def get_host_hwaddr(tap):
+    res = check_and_search_output(
+            ["ip", "addr", "show", "dev", tap, "scope", "link"],
+            r"link[^\s]+\s+(?P<hwaddr>[0-9A-Fa-f:]+)",
+            "hwaddr"
+        )
+    if res is None:
+        raise AssertionError(
+                "Can't find host hardware address on interface {}".format(tap)
+            )
+    else:
+        return res
+
+
+def pktbuf_empty(child):
+    child.sendline("pktbuf")
+    child.expect(r"packet buffer: first byte: (?P<first_byte>0x[0-9a-fA-F]+), "
+                 r"last byte: 0x[0-9a-fA-F]+ \(size: (?P<size>\d+)\)")
+    first_byte = child.match.group("first_byte")
+    size = child.match.group("size")
+    child.expect(
+            r"~ unused: {} \(next: (\(nil\)|0), size: {}\) ~".format(
+                first_byte, size))
+
+
+def register_protnum(child):
+    child.sendline("ip reg")
+    child.expect("Registered to protocol number 59")
+
+
+def unregister(child):
+    child.sendline("ip unreg")
+    child.expect(r"Unregistered from protocol number \d")
+
+
+def get_first_interface(child):
+    child.sendline("ifconfig")
+    child.expect(r"Iface\s+(\d+)")
+    return int(child.match.group(1))
+
+
+def add_ipv6_address(child, iface, ipv6_addr):
+    child.sendline("ifconfig {} add {}".format(iface, ipv6_addr))
+    child.expect(r"success: added [a-f0-9:]+/\d+ to interface \d+")
+
+
+def del_ipv6_address(child, iface, ipv6_addr):
+    child.sendline("ifconfig {} del {}".format(iface, ipv6_addr))
+    child.expect(r"success: removed [a-f0-9:]+ to interface \d+")
+
+
+def add_neighbor(child, iface, ipv6_addr, hw_addr):
+    child.sendline("nib neigh add {} {} {}".format(iface, ipv6_addr, hw_addr))
+    child.sendline("nib neigh")
+    child.expect(r"{} dev #{} lladdr {}".format(ipv6_addr.lower(), iface,
+                                                hw_addr.upper()))
+
+
+def del_neighbor(child, iface, ipv6_addr):
+    child.sendline("nib neigh del {} {}".format(iface, ipv6_addr))
+
+
+def test_wrong_type(child, iface, hw_dst, ll_dst, ll_src):
+    p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) /
+             IPv6ExtHdrRouting(type=255, segleft=1, addresses=["abcd::1"]),
+             iface=iface, timeout=1, verbose=0)
+    assert(p is not None)
+    assert(ICMPv6ParamProblem in p)
+    assert(p[ICMPv6ParamProblem].code == 0)     # erroneous header field encountered
+    assert(p[ICMPv6ParamProblem].ptr == 42)     # routing header type field
+    pktbuf_empty(child)
+
+
+def test_seg_left_gt_len_addresses(child, iface, hw_dst, ll_dst, ll_src):
+    # send routing header with no (0) addresses but segleft set to a value
+    # larger than 0
+    p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) /
+             IPv6ExtHdrRouting(type=3, segleft=18, addresses=[]),
+             iface=iface, timeout=1, verbose=0)
+    assert(p is not None)
+    assert(ICMPv6ParamProblem in p)
+    assert(p[ICMPv6ParamProblem].code == 0)     # erroneous header field encountered
+    assert(p[ICMPv6ParamProblem].ptr == 43)     # segleft field
+    pktbuf_empty(child)
+
+
+def test_multicast_dst(child, iface, hw_dst, ll_dst, ll_src):
+    # sniffing for ICMPv6 parameter problem message
+    sniffer.start_sniff(lambda p: p.haslayer(ICMPv6ParamProblem))
+    # send routing header with multicast destination
+    sendp(Ether(dst=hw_dst) / IPv6(dst="ff02::1", src=ll_src) /
+          IPv6ExtHdrRouting(type=3, segleft=1, addresses=["abcd::1"]),
+          iface=iface, verbose=0)
+    ps = sniffer.wait_for_sniff_results()
+    p = [p for p in ps if ICMPv6ParamProblem in p]
+    assert(len(p) > 0)
+    p = p[0]
+    assert(p[ICMPv6ParamProblem].code == 0)     # erroneous header field encountered
+    assert(p[ICMPv6ParamProblem].ptr == 24)     # IPv6 headers destination field
+    pktbuf_empty(child)
+
+
+def test_multicast_addr(child, iface, hw_dst, ll_dst, ll_src):
+    # Send routing header with multicast address in its destinations
+    p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) /
+             IPv6ExtHdrRouting(type=3, segleft=1, addresses=["ff02::1"]),
+             iface=iface, timeout=1, verbose=0)
+    assert(p is not None)
+    assert(ICMPv6ParamProblem in p)
+    assert(p[ICMPv6ParamProblem].code == 0)     # erroneous header field encountered
+    assert(p[ICMPv6ParamProblem].ptr == 48)     # first address in routing header
+    pktbuf_empty(child)
+
+
+def test_multiple_addrs_of_mine_uncomp(child, iface, hw_dst, ll_dst, ll_src):
+    dummy = "affe::1"
+    # add dummy IPv6 address
+    dst_iface = get_first_interface(child)
+    add_ipv6_address(child, dst_iface, dummy)
+    p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) /
+             IPv6ExtHdrRouting(type=3, segleft=3, addresses=[ll_dst, ll_src,
+                                                             dummy]),
+             iface=iface, timeout=1, verbose=0)
+    assert(p is not None)
+    assert(ICMPv6ParamProblem in p)
+    assert(p[ICMPv6ParamProblem].code == 0)             # erroneous header field encountered
+    assert(p[ICMPv6ParamProblem].ptr == 40+8+(2 * 16))  # dummy in routing header
+    pktbuf_empty(child)
+    del_ipv6_address(child, dst_iface, dummy)
+
+
+def test_forward_uncomp(child, iface, hw_dst, ll_dst, ll_src):
+    dummy = "affe::1"
+    hl = random.randint(2, 255)
+    # sniffing for packets to dummy
+    sniffer.start_sniff(lambda p: p[Ether].src == hw_dst)
+    # add dummy IPv6 address
+    dst_iface = get_first_interface(child)
+    hw_src = get_host_hwaddr(iface)
+    add_neighbor(child, dst_iface, dummy, hw_src)
+    sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src, hlim=hl) /
+          IPv6ExtHdrRouting(type=3, segleft=1, addresses=[dummy]),
+          iface=iface, verbose=0)
+    ps = sniffer.wait_for_sniff_results()
+    p = [p for p in ps if p[Ether].src == hw_dst]
+    assert(len(p) > 0)
+    p = p[0]
+    assert(IPv6 in p)
+    assert(IPv6ExtHdrRouting in p)
+    assert(p[IPv6].src == ll_src)
+    assert(p[IPv6].dst == dummy)
+    assert(p[IPv6].hlim == (hl - 1))
+    assert(p[IPv6ExtHdrRouting].type == 3)
+    assert(p[IPv6ExtHdrRouting].segleft == 0)
+    pktbuf_empty(child)
+    del_neighbor(child, dst_iface, dummy)
+
+
+def test_forward_uncomp_not_first_ext_hdr(child, iface, hw_dst, ll_dst, ll_src):
+    dummy = "affe::1"
+    hl = random.randint(2, 255)
+    # sniffing for packets to dummy
+    sniffer.start_sniff(lambda p: p[Ether].src == hw_dst)
+    # add dummy IPv6 address
+    dst_iface = get_first_interface(child)
+    hw_src = get_host_hwaddr(iface)
+    add_neighbor(child, dst_iface, dummy, hw_src)
+    sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src, hlim=hl) /
+          IPv6ExtHdrHopByHop() /
+          IPv6ExtHdrRouting(type=3, segleft=1, addresses=[dummy]),
+          iface=iface, verbose=0)
+    ps = sniffer.wait_for_sniff_results()
+    p = [p for p in ps if p[Ether].src == hw_dst]
+    assert(len(p) > 0)
+    p = p[0]
+    assert(IPv6 in p)
+    assert(IPv6ExtHdrRouting in p)
+    assert(p[IPv6].src == ll_src)
+    assert(p[IPv6].dst == dummy)
+    assert(p[IPv6].hlim == (hl - 1))
+    assert(p[IPv6ExtHdrRouting].type == 3)
+    assert(p[IPv6ExtHdrRouting].segleft == 0)
+    pktbuf_empty(child)
+    del_neighbor(child, dst_iface, dummy)
+
+
+def test_seq_left_0(child, iface, hw_dst, ll_dst, ll_src):
+    register_protnum(child)
+    sendp(Ether(dst=hw_dst) / IPv6(dst=ll_dst, src=ll_src) /
+          IPv6ExtHdrRouting(type=3, segleft=0), iface=iface, verbose=0)
+    # we are the target, so the packet should be dumped
+    # empty snip
+    child.expect(r"~~ SNIP  0 - size:\s+0 byte, type: NETTYPE_UNDEF \(\d+\)")
+    ipv6_payload_len = 0
+    # parsed routing header
+    child.expect(r"~~ SNIP  1 - size:\s+(\d+) byte, type: NETTYPE_\w+ \(\d+\)")
+    ipv6_payload_len += int(child.match.group(1))
+    # NH = 59 (IPV6_NONXT), len = 0x00, routing type = 3, segments left = 0
+    child.expect(r"00000000  3B  00  03  00  00  00  00  00")
+    # IPv6 header
+    child.expect(r"~~ SNIP  2 - size:\s+40 byte, type: NETTYPE_IPV6 \(\d+\)")
+    child.expect_exact(r"length: {}  next header: {}".format(
+            ipv6_payload_len, EXT_HDR_NH[IPv6ExtHdrRouting]
+        ))
+    child.expect_exact(r"destination address: {}".format(ll_dst))
+    pktbuf_empty(child)
+    unregister(child)
+
+
+def test_time_exc(child, iface, hw_dst, ll_dst, ll_src):
+    dummy = "affe::1"
+    p = srp1(Ether(dst=hw_dst) / IPv6(dst=ll_dst, hlim=1, src=ll_src) /
+             IPv6ExtHdrRouting(type=3, segleft=1, addresses=[dummy]),
+             iface=iface, timeout=1, verbose=0)
+    assert(p is not None)
+    assert(ICMPv6TimeExceeded in p)
+    assert(p[ICMPv6TimeExceeded].code == 0)
+    pktbuf_empty(child)
+
+
+def testfunc(child):
+    global sniffer
+    tap = get_bridge(os.environ["TAP"])
+
+    child.expect(r"OK \((\d+) tests\)")     # wait for and check result of unittests
+    print("." * int(child.match.group(1)), end="", flush=True)
+    lladdr_src = get_host_lladdr(tap)
+    child.sendline("ifconfig")
+    child.expect("HWaddr: (?P<hwaddr>[A-Fa-f:0-9]+)")
+    hwaddr_dst = child.match.group("hwaddr").lower()
+    child.expect("(?P<lladdr>fe80::[A-Fa-f:0-9]+)")
+    lladdr_dst = child.match.group("lladdr").lower()
+    sniffer = Sniffer(tap)
+    sniffer.start()
+
+    def run(func):
+        if child.logfile == sys.stdout:
+            func(child, tap, hwaddr_dst, lladdr_dst, lladdr_src)
+        else:
+            try:
+                func(child, tap, hwaddr_dst, lladdr_dst, lladdr_src)
+                print(".", end="", flush=True)
+            except Exception as e:
+                print("FAILED")
+                raise e
+
+    run(test_wrong_type)
+    run(test_seg_left_gt_len_addresses)
+    run(test_multicast_dst)
+    run(test_multicast_addr)
+    run(test_multiple_addrs_of_mine_uncomp)
+    run(test_forward_uncomp)
+    run(test_forward_uncomp_not_first_ext_hdr)
+    # compressed tests hard to implement with scapy and also covered in
+    # unittests
+    run(test_seq_left_0)
+    run(test_time_exc)
+    print("SUCCESS")
+    sniffer.stop()
+
+
+if __name__ == "__main__":
+    if os.geteuid() != 0:
+        print("\x1b[1;31mThis test requires root privileges.\n"
+              "It's constructing and sending Ethernet frames.\x1b[0m\n",
+              file=sys.stderr)
+        sys.exit(1)
+    sys.exit(run(testfunc, timeout=1, echo=False))
diff --git a/tests/unittests/tests-gnrc_rpl_srh/Makefile b/tests/unittests/tests-gnrc_rpl_srh/Makefile
deleted file mode 100644
index 48422e909a47d7cd428d10fa73825060ccc8d8c2..0000000000000000000000000000000000000000
--- a/tests/unittests/tests-gnrc_rpl_srh/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-include $(RIOTBASE)/Makefile.base
diff --git a/tests/unittests/tests-gnrc_rpl_srh/Makefile.include b/tests/unittests/tests-gnrc_rpl_srh/Makefile.include
deleted file mode 100644
index 4aa358aa3cfb60facec2b0432d3f4bc64bdbef88..0000000000000000000000000000000000000000
--- a/tests/unittests/tests-gnrc_rpl_srh/Makefile.include
+++ /dev/null
@@ -1,3 +0,0 @@
-USEMODULE += gnrc_ipv6
-USEMODULE += ipv6_addr
-USEMODULE += gnrc_rpl_srh
diff --git a/tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.h b/tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.h
deleted file mode 100644
index 50e3725e9123a6b539f28eadfd11741de02fa207..0000000000000000000000000000000000000000
--- a/tests/unittests/tests-gnrc_rpl_srh/tests-gnrc_rpl_srh.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @addtogroup  unittests
- * @{
- *
- * @file
- * @brief       Unittests for the ``gnrc_rpl_srh`` module
- *
- * @author      Cenk Gündoğan <mail@cgundogan.de>
- */
-#ifndef TESTS_GNRC_RPL_SRH_H
-#define TESTS_GNRC_RPL_SRH_H
-
-#include "embUnit.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief   The entry point of this test suite.
- */
-void tests_gnrc_rpl_srh(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TESTS_GNRC_RPL_SRH_H */
-/** @} */