diff --git a/Reconnoitre/lib/file_helper.py b/Reconnoitre/lib/file_helper.py
index 93068d9..9ad1c4c 100644
--- a/Reconnoitre/lib/file_helper.py
+++ b/Reconnoitre/lib/file_helper.py
@@ -1,169 +1,215 @@
+#!/usr/bin/python
 import os
 import json
 
 
-def check_directory(output_directory):
-    try:
-        os.stat(output_directory)
-    except Exception:
-        os.mkdir(output_directory)
-        print("[!] %s didn't exist and has been created." % output_directory)
-
-
-def load_targets(target_hosts, output_directory, quiet):
-    if (os.path.isdir(target_hosts) or os.path.isfile(target_hosts)):
-        return target_hosts
-    elif "-" in target_hosts:
-        expand_targets(target_hosts, output_directory)
-        return output_directory + "/targets.txt"
-    else:
-        return output_directory + "/targets.txt"
-
-
-def expand_targets(target_hosts, output_directory):
-    parts = target_hosts.split(".")
-    target_list = []
-    for part in parts:
-        if "-" in part:
-            iprange = part.split("-")
-    for i in range(int(iprange[0]), int(iprange[1])):
-        target_list.append(
-            parts[0] +
-            "." +
-            parts[1] +
-            "." +
-            parts[2] +
-            "." +
-            str(i))
-    with open(output_directory + "/targets.txt", "w") as targets:
-        for target in target_list:
-            targets.write("%s\n" % target)
-
-
-def create_dir_structure(ip_address, output_directory):
-    print("[+] Creating directory structure for " + ip_address)
-
-    hostdir = output_directory + "/" + ip_address
-    try:
-        os.stat(hostdir)
-    except Exception:
-        os.mkdir(hostdir)
-
-    nmapdir = hostdir + "/scans"
-    print("   [>] Creating scans directory at: %s" % nmapdir)
-    try:
-        os.stat(nmapdir)
-    except Exception:
-        os.mkdir(nmapdir)
-
-    exploitdir = hostdir + "/exploit"
-    print("   [>] Creating exploit directory at: %s" % exploitdir)
-    try:
-        os.stat(exploitdir)
-    except Exception:
-        os.mkdir(exploitdir)
-
-    lootdir = hostdir + "/loot"
-    print("   [>] Creating loot directory at: %s" % lootdir)
-    try:
-        os.stat(lootdir)
-    except Exception:
-        os.mkdir(lootdir)
-
-    prooffile = hostdir + "/proof.txt"
-    print("   [>] Creating proof file at: %s" % prooffile)
-    open(prooffile, 'a').close()
-
-
-def write_recommendations(results, ip_address, outputdir):
-    recommendations_file = outputdir + "/" + ip_address + "_findings.txt"
-    serv_dict = {}
-    lines = results.split("\n")
-    for line in lines:
-        ports = []
-        line = line.strip()
-        if ("tcp" in line) and ("open" in line) and not ("Discovered" in line):
-            while "  " in line:
-                line = line.replace("  ", " ")
-            service = line.split(" ")[2]
-            port = line.split(" ")[0]
-
-            if service in serv_dict:
-                ports = serv_dict[service]
-
-            ports.append(port)
-            serv_dict[service] = ports
-
-    print("[+] Writing findings for %s" % (ip_address))
-
-    __location__ = os.path.realpath(
-        os.path.join(
-            os.getcwd(),
-            os.path.dirname(__file__)))
-    with open(os.path.join(__location__, "config.json"), "r") as config:
-        c = config.read()
-        j = json.loads(
-            c.replace(
-                "$ip",
-                "%(ip)s").replace(
-                "$port",
-                "%(port)s").replace(
-                "$outputdir",
-                "%(outputdir)s"))
-
-    f = open(recommendations_file, 'w')
-    for serv in serv_dict:
-        ports = serv_dict[serv]
-
-        for service in j["services"]:
-            if (serv in j["services"][service]
-                    ["nmap-service-names"]) or (service in serv):
-                for port in ports:
-                    port = port.split("/")[0]
-
-                    description = ("[*] "
-                                   + j["services"][service]["description"])
-                    print(description % {"ip": ip_address, "port": port})
-                    f.write((description + "\n") %
-                            {"ip": ip_address, "port": port})
-
-                    for entry in j["services"][service]["output"]:
-                        f.write("   [*] " + entry["description"] + "\n")
-
-                        for cmd in entry["commands"]:
-                            f.write(("      [=] " + cmd + "\n") %
-                                    {"ip": ip_address,
-                                     "port": port,
-                                     "outputdir": outputdir})
-
-                    f.write("\n")
-
-    f.write(
-        "\n\n[*] Always remember to manually go over the"
-        " portscan report and carefully read between the lines ;)")
-    f.close()
-
-
-def get_config_options(key, *args):
-    __location__ = os.path.realpath(
-        os.path.join(
-            os.getcwd(),
-            os.path.dirname(__file__)))
-    with open(os.path.join(__location__, "config.json"), "r") as config:
-        c = config.read()
-        j = json.loads(
-            c.replace(
-                "$ip",
-                "%(ip)s").replace(
-                "$port",
-                "%(port)s").replace(
-                "$outputdir",
-                "%(outputdir)s"))
-
-        res = j.get(key, None)
-        for arg in args:
-            res = res.get(arg, None)
-            if res is None:
-                raise KeyError
-
-        return res
+class FileHelper(object):
+
+    @staticmethod
+    def check_directory(output_directory):
+        try:
+            assert (os.path.exists(output_directory) and os.path.isdir(output_directory))
+        except AssertionError:
+            print(f"[!] Output directory {output_directory} does not exist. Creating it.")
+            FileHelper.make_directory(output_directory)
+        finally:
+            return output_directory
+
+    @staticmethod
+    def make_directory(output_directory):
+        try:
+            os.mkdir(output_directory)
+        except FileExistsError as err:
+            print(f"[!] Directory {output_directory} already exists.")
+            raise err
+
+    @staticmethod
+    def check_file(file):
+        try:
+            assert (os.path.exists(file) and os.path.isfile(file))
+        except AssertionError:
+            print(f"[!] File {file} does not exist. Creating it.")
+            FileHelper.make_file(file)
+        finally:
+            return file
+
+    @staticmethod
+    def make_file(file):
+        try:
+            with open(file, "w") as f:
+                print(f"[+] Created new file {f.name}")
+        except FileExistsError as err:
+            print(f"[!] File {file} already exists.")
+            raise err
+
+    @staticmethod
+    def load_targets(target_hosts, output_directory, quiet):
+        if (os.path.isdir(target_hosts) or os.path.isfile(target_hosts)):
+            return target_hosts
+        elif "-" in target_hosts:
+            FileHelper.expand_targets(target_hosts, output_directory)
+            return output_directory + "/targets.txt"
+        else:
+            return output_directory + "/targets.txt"
+
+    @staticmethod
+    def expand_targets(target_hosts, output_directory):
+        iprange = None
+        target_list = []
+        if "-" not in target_hosts:
+            return
+
+        try:
+            parts = target_hosts.split(".")
+            for part in parts:
+                if "-" in part:
+                    iprange = part.split("-")
+        except FileHelperException as err:
+            raise err
+        else:
+            for i in range(int(iprange[0]), int(iprange[1])):
+                target_list.append(
+                    parts[0] +
+                    "." +
+                    parts[1] +
+                    "." +
+                    parts[2] +
+                    "." +
+                    str(i))
+        target_list = []
+        with open(output_directory + "/targets.txt", "w") as targets:
+            for target in target_list:
+                targets.write("%s\n" % target)
+
+    @staticmethod
+    def create_dir_structure(ip_address, output_directory):
+        print("[+] Creating directory structure for " + ip_address)
+
+        hostdir = output_directory + "/" + ip_address
+        try:
+            os.stat(hostdir)
+        except OSError:
+            os.mkdir(hostdir)
+
+        nmapdir = hostdir + "/scans"
+        print("   [>] Creating scans directory at: %s" % nmapdir)
+        try:
+            os.stat(nmapdir)
+        except OSError:
+            os.mkdir(nmapdir)
+
+        exploitdir = hostdir + "/exploit"
+        print("   [>] Creating exploit directory at: %s" % exploitdir)
+        try:
+            os.stat(exploitdir)
+        except OSError:
+            os.mkdir(exploitdir)
+
+        lootdir = hostdir + "/loot"
+        print("   [>] Creating loot directory at: %s" % lootdir)
+        try:
+            os.stat(lootdir)
+        except OSError:
+            os.mkdir(lootdir)
+
+        prooffile = hostdir + "/proof.txt"
+        print("   [>] Creating proof file at: %s" % prooffile)
+        open(prooffile, "a").close()
+
+    @staticmethod
+    def write_recommendations(results, ip_address, outputdir):
+        recommendations_file = outputdir + "/" + ip_address + "_findings.txt"
+        serv_dict = {}
+        lines = results.split("\n")
+        for line in lines:
+            ports = []
+            line = line.strip()
+            if ("tcp" in line) and ("open" in line) and not ("Discovered" in line):
+                while "  " in line:
+                    line = line.replace("  ", " ")
+                service = line.split(" ")[2]
+                port = line.split(" ")[0]
+
+                if service in serv_dict:
+                    ports = serv_dict[service]
+
+                ports.append(port)
+                serv_dict[service] = ports
+
+        print("[+] Writing findings for %s" % (ip_address))
+
+        __location__ = os.path.realpath(
+            os.path.join(
+                os.getcwd(),
+                os.path.dirname(__file__)))
+        with open(os.path.join(__location__, "config.json"), "r") as config:
+            c = config.read()
+            j = json.loads(
+                c.replace(
+                    "$ip",
+                    "%(ip)s").replace(
+                    "$port",
+                    "%(port)s").replace(
+                    "$outputdir",
+                    "%(outputdir)s"))
+
+        f = open(recommendations_file, "w")
+        for serv in serv_dict:
+            ports = serv_dict[serv]
+
+            for service in j["services"]:
+                if (serv in j["services"][service]
+                        ["nmap-service-names"]) or (service in serv):
+                    for port in ports:
+                        port = port.split("/")[0]
+
+                        description = ("[*] "
+                                       + j["services"][service]["description"])
+                        print(description % {"ip": ip_address, "port": port})
+                        f.write((description + "\n") %
+                                {"ip": ip_address, "port": port})
+
+                        for entry in j["services"][service]["output"]:
+                            f.write("   [*] " + entry["description"] + "\n")
+
+                            for cmd in entry["commands"]:
+                                f.write(("      [=] " + cmd + "\n") %
+                                        {"ip": ip_address,
+                                         "port": port,
+                                         "outputdir": outputdir})
+
+                        f.write("\n")
+
+        f.write(
+            "\n\n[*] Always remember to manually go over the"
+            " portscan report and carefully read between the lines ;)")
+        f.close()
+
+    @staticmethod
+    def get_config_options(key, *args):
+        __location__ = os.path.realpath(
+            os.path.join(
+                os.getcwd(),
+                os.path.dirname(__file__)))
+        with open(os.path.join(__location__, "config.json"), "r") as config:
+            c = config.read()
+            j = json.loads(
+                c.replace(
+                    "$ip",
+                    "%(ip)s").replace(
+                    "$port",
+                    "%(port)s").replace(
+                    "$outputdir",
+                    "%(outputdir)s"))
+
+            res = j.get(key, None)
+            for arg in args:
+                res = res.get(arg, None)
+                if res is None:
+                    raise KeyError
+
+            return res
+
+
+class FileHelperException(Exception):
+    pass
diff --git a/Reconnoitre/lib/find_dns.py b/Reconnoitre/lib/find_dns.py
index fb6ec90..15a5d5e 100644
--- a/Reconnoitre/lib/find_dns.py
+++ b/Reconnoitre/lib/find_dns.py
@@ -1,51 +1,65 @@
-from Reconnoitre.lib.file_helper import check_directory
-from Reconnoitre.lib.file_helper import load_targets
+#!/usr/bin/python
+from Reconnoitre.lib.file_helper import FileHelper
 from Reconnoitre.lib.subprocess_helper import run_scan
 
 
-def find_dns(target_hosts, output_directory, quiet):
-    check_directory(output_directory)
-    dns_server_list = []
-    results = 0
-    hostcount = 0
-    dnscount = 0
-
-    output_file = open(output_directory + "/DNS-Detailed.txt", 'w')
-    output_targets = open(output_directory + "/DNS-targets.txt", 'w')
-
-    targets = load_targets(target_hosts, output_directory, quiet)
-    target_file = open(targets, 'r')
-
-    print("[*] Loaded targets from: %s" % targets)
-    print("[+] Enumerating TCP port 53 over targets to find dns servers")
-
-    for ip_address in target_file:
-        hostcount += 1
-        ip_address = ip_address.strip()
-        ip_address = ip_address.rstrip()
-
-        print("   [>] Testing %s for DNS" % ip_address)
-        DNSSCAN = "nmap -n -sV -Pn -vv -p53 %s" % (ip_address)
-        results = run_scan(DNSSCAN)
-        lines = results.split("\n")
-
-        for line in lines:
-            line = line.strip()
-            line = line.rstrip()
-            if (("53/tcp" in line) and ("open" in line)
-                    and ("Discovered" not in line)):
-                print(
-                    "      [=] Found DNS service running on: %s" %
-                    (ip_address))
-                output_file.write(
-                    "[*] Found DNS service running on: %s\n" %
-                    (ip_address))
-                output_file.write("   [>] %s\n" % (line))
-                output_targets.write("%s\n" % (ip_address))
-                dns_server_list.append(ip_address)
-                dnscount += 1
-    print("[*] Found %s DNS servers within %s hosts" %
-          (str(dnscount), str(hostcount)))
-    output_file.close()
-    output_targets.close()
-    return '' if len(dns_server_list) == 0 else ','.join(dns_server_list)
+class FindDns(object):
+
+    def __init__(
+            self,
+            target_hosts,
+            output_directory,
+            quiet):
+
+        self.target_hosts = target_hosts
+        self.output_directory = output_directory
+        self.output_file = f"{self.output_directory}/DNS-Detailed.txt"
+        self.output_targets = f"{self.output_directory}/DNS-targets.txt"
+        self.quiet = quiet
+        self.dns_server_list = []
+        self.results = 0
+        self.hostcount = 0
+        self.dnscount = 0
+
+    def find_dns(self):
+        FileHelper.check_directory(output_directory=self.output_directory)
+        output_file = open(self.output_file, 'w')
+        output_targets = open(self.output_targets, 'w')
+        targets = FileHelper.load_targets(self.target_hosts, self.output_directory, self.quiet)
+        FileHelper.check_file(targets)
+        try:
+            target_file = open(targets, 'r')
+            print("[*] Loaded targets from: %s" % targets)
+        except FileExistsError as err:
+            print("[!] Unable to load: %s" % targets)
+            raise err
+
+        print("[*] Loaded targets from: %s" % targets)
+        print("[+] Enumerating TCP port 53 over targets to find dns servers")
+
+        for ip_address in target_file:
+            self.hostcount += 1
+            ip_address = ip_address.strip()
+            ip_address = ip_address.rstrip()
+
+            print("   [>] Testing %s for DNS" % ip_address)
+            DNSSCAN = "nmap -n -sV -Pn -vv -p53 %s" % (ip_address)
+            results = run_scan(DNSSCAN)
+            lines = results.split("\n")
+
+            for line in lines:
+                line = line.strip()
+                line = line.rstrip()
+                if (("53/tcp" in line) and ("open" in line) and ("Discovered" not in line)):
+                    print("      [=] Found DNS service running on: %s" % (ip_address))
+                    output_file.write("[*] Found DNS service running on: %s\n" % (ip_address))
+                    output_file.write("   [>] %s\n" % (line))
+                    output_targets.write("%s\n" % (ip_address))
+                    self.dns_server_list.append(ip_address)
+                    self.dnscount += 1
+
+        print("[*] Found %s DNS servers within %s hosts" % (str(self.dnscount), str(self.hostcount)))
+        output_file.close()
+        output_targets.close()
+        target_file.close()
+        return '' if len(self.dns_server_list) == 0 else ','.join(self.dns_server_list)
diff --git a/Reconnoitre/lib/hostname_scan.py b/Reconnoitre/lib/hostname_scan.py
index 09e985e..9d25593 100644
--- a/Reconnoitre/lib/hostname_scan.py
+++ b/Reconnoitre/lib/hostname_scan.py
@@ -1,48 +1,61 @@
+#!/usr/bin/python
+from Reconnoitre.lib.file_helper import FileHelper
+from Reconnoitre.lib.subprocess_helper import run_scan
 import os
 
-from Reconnoitre.lib.file_helper import check_directory
-from Reconnoitre.lib.subprocess_helper import run_scan
 
+class HostnameScan(object):
+
+    def __init__(
+            self,
+            target_hosts,
+            output_directory,
+            quiet):
+
+        self.target_hosts = target_hosts
+        self.output_directory = output_directory
+        self.output_file = f"{self.output_directory}/hostnames.txt"
+        self.quiet = quiet
+        self.hostnames = 0
 
-def hostname_scan(target_hosts, output_directory, quiet):
-    check_directory(output_directory)
-    output_file = output_directory + "/hostnames.txt"
-    f = open(output_file, 'w')
-    print("[+] Writing hostnames to: %s" % output_file)
+    def hostname_scan(self):
+        FileHelper.check_directory(self.output_directory)
+        FileHelper.check_file(self.output_file)
+        f = open(self.output_file, 'w')
+        print("[+] Writing hostnames to: %s" % self.output_file)
 
-    hostnames = 0
-    SWEEP = ''
+        SWEEP = ''
 
-    if (os.path.isfile(target_hosts)):
-        SWEEP = "nbtscan -q -f %s" % (target_hosts)
-    else:
-        SWEEP = "nbtscan -q %s" % (target_hosts)
+        if (os.path.isfile(self.target_hosts)):
+            SWEEP = "nbtscan -q -f %s" % (self.target_hosts)
+        else:
+            SWEEP = "nbtscan -q %s" % (self.target_hosts)
 
-    results = run_scan(SWEEP)
-    lines = results.split("\n")
+        results = run_scan(SWEEP)
+        lines = results.split("\n")
 
-    for line in lines:
-        line = line.strip()
-        line = line.rstrip()
+        for line in lines:
+            line = line.strip()
+            line = line.rstrip()
 
-        # Final line is blank which causes list index issues if we don't
-        # continue past it.
-        if " " not in line:
-            continue
+            # Final line is blank which causes list index issues if we don't
+            # continue past it.
+            if " " not in line:
+                continue
 
-        while "  " in line:
-            line = line.replace("  ", " ")
+            while "  " in line:
+                line = line.replace("  ", " ")
 
-        ip_address = line.split(" ")[0]
-        host = line.split(" ")[1]
+            ip_address = line.split(" ")[0]
+            host = line.split(" ")[1]
 
-        if (hostnames > 0):
-            f.write('\n')
+            if (self.hostnames > 0):
+                f.write('\n')
 
-        print("   [>] Discovered hostname: %s (%s)" % (host, ip_address))
-        f.write("%s - %s" % (host, ip_address))
-        hostnames += 1
+            print("   [>] Discovered hostname: %s (%s)" % (host, ip_address))
+            f.write("%s - %s" % (host, ip_address))
+            self.hostnames += 1
 
-    print("[*] Found %s hostnames." % (hostnames))
-    print("[*] Created hostname list %s" % (output_file))
-    f.close()
+        print("[*] Found %s hostnames." % (self.hostnames))
+        print("[*] Created hostname list %s" % (self.output_file))
+        f.close()
diff --git a/Reconnoitre/lib/ping_sweeper.py b/Reconnoitre/lib/ping_sweeper.py
index 6d2c660..584085d 100644
--- a/Reconnoitre/lib/ping_sweeper.py
+++ b/Reconnoitre/lib/ping_sweeper.py
@@ -1,44 +1,51 @@
-from Reconnoitre.lib.file_helper import check_directory
+#!/usr/bin/python
+from Reconnoitre.lib.file_helper import FileHelper
 from Reconnoitre.lib.subprocess_helper import run_scan
 
 
-def ping_sweeper(target_hosts, output_directory, quiet):
-    check_directory(output_directory)
-    output_file = output_directory + "/targets.txt"
+class PingSweeper(object):
 
-    print("[+] Performing ping sweep over %s" % target_hosts)
+    def __init__(
+            self,
+            target_hosts,
+            output_directory,
+            quiet):
 
-    lines = call_nmap_sweep(target_hosts)
-    live_hosts = parse_nmap_output_for_live_hosts(lines)
-    write_live_hosts_list_to_file(output_file, live_hosts)
+        self.target_hosts = target_hosts
+        self.output_directory = output_directory
+        self.output_file = f"{self.output_directory}/targets.txt"
+        self.quiet = quiet
+        self.live_hosts = None
+        self.nmap_lines = None
 
-    for ip_address in live_hosts:
-        print("   [>] Discovered host: %s" % (ip_address))
+    def ping_sweeper(self):
+        FileHelper.check_directory(output_directory=self.output_directory)
+        print("[+] Performing ping sweep over %s" % self.target_hosts)
 
-    print("[*] Found %s live hosts" % (len(live_hosts)))
-    print("[*] Created target list %s" % (output_file))
+        self.call_nmap_sweep()
+        self.parse_nmap_output_for_live_hosts()
+        self.write_live_hosts_list_to_file()
 
+        for ip_address in self.live_hosts:
+            print("   [>] Discovered host: %s" % (ip_address))
 
-def call_nmap_sweep(target_hosts):
-    SWEEP = "nmap -n -sP %s" % (target_hosts)
+        print("[*] Found %s live hosts" % (len(self.live_hosts)))
+        print("[*] Created target list %s" % (self.output_file))
 
-    results = run_scan(SWEEP)
-    lines = str(results).split("\n")
-    return lines
+    def call_nmap_sweep(self):
+        SWEEP = "nmap -n -sP %s" % (self.target_hosts)
+        results = run_scan(SWEEP)
+        self.nmap_lines = str(results).split("\n")
 
+    def parse_nmap_output_for_live_hosts(self):
+        def get_ip_from_nmap_line(line):
+            return line.split()[4]
 
-def parse_nmap_output_for_live_hosts(lines):
-    def get_ip_from_nmap_line(line):
-        return line.split()[4]
+        self.live_hosts = [get_ip_from_nmap_line(line)
+                      for line in self.nmap_lines
+                      if "Nmap scan report for" in line]
 
-    live_hosts = [get_ip_from_nmap_line(line)
-                  for line in lines
-                  if "Nmap scan report for" in line]
-
-    return live_hosts
-
-
-def write_live_hosts_list_to_file(output_file, live_hosts):
-    print("[+] Writing discovered targets to: %s" % output_file)
-    with open(output_file, 'w') as f:
-        f.write("\n".join(live_hosts))
+    def write_live_hosts_list_to_file(self):
+        print(f"[+] Writing discovered targets to: {self.output_file}")
+        with open(self.output_file, "w") as f:
+            f.write("\n".join(self.live_hosts))
diff --git a/Reconnoitre/lib/service_scan.py b/Reconnoitre/lib/service_scan.py
index d530bc0..a8beee0 100644
--- a/Reconnoitre/lib/service_scan.py
+++ b/Reconnoitre/lib/service_scan.py
@@ -1,163 +1,111 @@
+#!/usr/bin/python
+from Reconnoitre.lib.file_helper import FileHelper
+from Reconnoitre.lib.subprocess_helper import run_scan
 import multiprocessing
 import socket
 
-from Reconnoitre.lib.file_helper import check_directory
-from Reconnoitre.lib.file_helper import create_dir_structure
-from Reconnoitre.lib.file_helper import get_config_options
-from Reconnoitre.lib.file_helper import load_targets
-from Reconnoitre.lib.file_helper import write_recommendations
-from Reconnoitre.lib.subprocess_helper import run_scan
-
 
-def nmap_scan(
-        ip_address,
-        output_directory,
-        dns_server,
-        quick,
-        no_udp_service_scan):
-    ip_address = ip_address.strip()
-
-    print("[+] Starting quick nmap scan for %s" % (ip_address))
-    flags = get_config_options('nmap', 'quickscan')
-    QUICKSCAN = f"nmap {flags} {ip_address} -oA '{output_directory}/{ip_address}.quick'"
-    quickresults = run_scan(QUICKSCAN)
-
-    write_recommendations(quickresults, ip_address, output_directory)
-    print("[*] TCP quick scans completed for %s" % ip_address)
-
-    if (quick):
-        return
-
-    if dns_server:
-        print(
-            "[+] Starting detailed TCP%s nmap scans for "
-            "%s using DNS Server %s" %
-            (("" if no_udp_service_scan is True else "/UDP"),
-             ip_address,
-             dns_server))
-        print("[+] Using DNS server %s" % (dns_server))
-        flags = get_config_options("nmap", "tcpscan")
-        TCPSCAN = f"nmap {flags} --dns-servers {dns_server} -oN\
-        '{output_directory}/{ip_address}.nmap' -oX\
-        '{output_directory}/{ip_address}_nmap_scan_import.xml' {ip_address}"
-
-        flags = get_config_options("nmap", "dnsudpscan")
-        UDPSCAN = f"nmap {flags} \
-        --dns-servers {dns_server} -oN '{output_directory}/{ip_address}U.nmap' \
-        -oX '{output_directory}/{ip_address}U_nmap_scan_import.xml' {ip_address}"
-
-    else:
-        print("[+] Starting detailed TCP%s nmap scans for %s" % (
-            ("" if no_udp_service_scan is True else "/UDP"), ip_address))
-        flags = get_config_options("nmap", "tcpscan")
-        TCPSCAN = f"nmap {flags} -oN\
-        '{output_directory}/{ip_address}.nmap' -oX\
-        '{output_directory}/{ip_address}_nmap_scan_import.xml' {ip_address}"
-
-        flags = get_config_options("nmap", "udpscan")
-        UDPSCAN = f"nmap {flags} {ip_address} -oA '{output_directory}/{ip_address}-udp'"
-
-    udpresult = "" if no_udp_service_scan is True else run_scan(UDPSCAN)
-    tcpresults = run_scan(TCPSCAN)
-
-    write_recommendations(tcpresults + udpresult, ip_address, output_directory)
-    print("[*] TCP%s scans completed for %s" %
-          (("" if no_udp_service_scan is True else "/UDP"), ip_address))
-
-
-def valid_ip(address):
-    try:
-        socket.inet_aton(address)
-        return True
-    except socket.error:
-        return False
-
-
-def target_file(
-        target_hosts,
-        output_directory,
-        dns_server,
-        quiet,
-        quick,
-        no_udp_service_scan):
-    targets = load_targets(target_hosts, output_directory, quiet)
-    target_file = open(targets, 'r')
-    try:
-        target_file = open(targets, 'r')
-        print("[*] Loaded targets from: %s" % targets)
-    except Exception:
-        print("[!] Unable to load: %s" % targets)
-
-    for ip_address in target_file:
-        ip_address = ip_address.strip()
-        create_dir_structure(ip_address, output_directory)
-
-        host_directory = output_directory + "/" + ip_address
-        nmap_directory = host_directory + "/scans"
+class ServiceScan(object):
 
-        jobs = []
-        p = multiprocessing.Process(
-            target=nmap_scan,
-            args=(
-                ip_address,
-                nmap_directory,
-                dns_server,
-                quick,
-                no_udp_service_scan))
-        jobs.append(p)
-        p.start()
-    target_file.close()
-
-
-def target_ip(
-        target_hosts,
-        output_directory,
-        dns_server,
-        quiet,
-        quick,
-        no_udp_service_scan):
-    print("[*] Loaded single target: %s" % target_hosts)
-    target_hosts = target_hosts.strip()
-    create_dir_structure(target_hosts, output_directory)
-
-    host_directory = output_directory + "/" + target_hosts
-    nmap_directory = host_directory + "/scans"
-
-    jobs = []
-    p = multiprocessing.Process(
-        target=nmap_scan,
-        args=(
-            target_hosts,
-            nmap_directory,
-            dns_server,
-            quick,
-            no_udp_service_scan))
-    jobs.append(p)
-    p.start()
-
-
-def service_scan(
-        target_hosts,
-        output_directory,
-        dns_server,
-        quiet,
-        quick,
-        no_udp_service_scan):
-    check_directory(output_directory)
-
-    if (valid_ip(target_hosts)):
-        target_ip(
+    def __init__(
+            self,
             target_hosts,
             output_directory,
             dns_server,
             quiet,
             quick,
-            no_udp_service_scan)
-    else:
-        target_file(
-            target_hosts,
-            output_directory,
-            dns_server,
-            quiet,
-            quick,
-            no_udp_service_scan)
+            no_udp_service_scan):
+
+        self.target_hosts = target_hosts
+        self.output_directory = output_directory
+        self.dns_server = dns_server
+        self.quiet = quiet
+        self.quick = quick
+        self.no_udp_service_scan = no_udp_service_scan
+        self.nmap_directory = f"{self.output_directory}/{self.target_hosts}/scans"
+        FileHelper.create_dir_structure(target_hosts, self.output_directory)
+
+    @staticmethod
+    def valid_ip(address):
+        try:
+            socket.inet_aton(address)
+            return True
+        except socket.error:
+            return False
+
+    def target_file(self):
+        targets = FileHelper.load_targets(self.target_hosts, self.output_directory, self.quiet)
+        FileHelper.check_file(targets)
+
+        try:
+            target_file = open(targets, 'r')
+            print(f"[*] Loaded targets from: {targets}")
+        except FileExistsError as err:
+            print(f"[!] Unable to load: {targets}")
+            raise err
+
+        for ip_address in target_file:
+            ip_address = ip_address.strip()
+            FileHelper.create_dir_structure(ip_address, self.output_directory)
+            nmap_directory = f"{self.output_directory}/{ip_address}/scans"
+            FileHelper.check_directory(output_directory=nmap_directory)
+            jobs = []
+            p = multiprocessing.Process(target=self.nmap_scan)
+            jobs.append(p)
+            p.start()
+        target_file.close()
+
+    def target_ip(self):
+        print(f"[*] Loaded single target: {self.target_hosts}")
+        target_hosts = self.target_hosts.strip()
+        FileHelper.create_dir_structure(target_hosts, self.output_directory)
+        FileHelper.check_directory(output_directory=self.nmap_directory)
+        jobs = []
+        p = multiprocessing.Process(target=self.nmap_scan)
+        jobs.append(p)
+        p.start()
+
+    def nmap_scan(self):
+        print(f"[+] Starting quick nmap scan for {self.target_hosts}")
+        flags = FileHelper.get_config_options('nmap', 'quickscan')
+        QUICKSCAN = f"nmap {flags} {self.target_hosts} -oA '{self.nmap_directory}.quick'"
+        quickresults = run_scan(QUICKSCAN)
+        FileHelper.write_recommendations(quickresults, self.target_hosts, self.output_directory)
+        print(f"[*] TCP quick scans completed for {self.target_hosts}")
+
+        if (self.quick):
+            return
+
+        if self.dns_server:
+            print(f"[+] Starting detailed TCP{('' if self.no_udp_service_scan is True else '/UDP')} nmap scans for {self.target_hosts} using DNS Server {self.dns_server}")
+            print("[+] Using DNS server %s" % (self.dns_server))
+            flags = FileHelper.get_config_options("nmap", "tcpscan")
+            TCPSCAN = f"nmap {flags} --dns-servers {self.dns_server} -oN '{self.nmap_directory}.nmap' -oX '{self.nmap_directory}/scan_import.xml' {self.target_hosts}"
+
+            flags = FileHelper.get_config_options("nmap", "dnsudpscan")
+            UDPSCAN = f"nmap {flags} --dns-servers {self.dns_server} -oN '{self.nmap_directory}U.nmap' -oX '{self.nmap_directory}/UDP_scan_import.xml' {self.target_hosts}"
+
+        else:
+            print(f"[+] Starting detailed TCP{('' if self.no_udp_service_scan is True else '/UDP')} nmap scans for {self.target_hosts}")
+            flags = FileHelper.get_config_options("nmap", "tcpscan")
+            TCPSCAN = f"nmap {flags} -oN '{self.nmap_directory}.nmap' -oX '{self.nmap_directory}/scan_import.xml' {self.target_hosts}"
+
+            flags = FileHelper.get_config_options("nmap", "udpscan")
+            UDPSCAN = f"nmap {flags} {self.target_hosts} -oA '{self.nmap_directory}-udp'"
+
+        if self.no_udp_service_scan:
+            udpresult = ""
+        else:
+            udpresult = run_scan(UDPSCAN)
+
+        tcpresults = run_scan(TCPSCAN)
+        FileHelper.write_recommendations(tcpresults + udpresult, self.target_hosts, self.output_directory)
+        print(f"[*] TCP{('' if self.no_udp_service_scan is True else '/UDP')} scans completed for {self.target_hosts}")
+
+    def service_scan(self):
+        FileHelper.check_directory(output_directory=self.output_directory)
+
+        if (self.valid_ip(self.target_hosts)):
+            self.target_ip()
+        else:
+            self.target_file()
diff --git a/Reconnoitre/lib/snmp_walk.py b/Reconnoitre/lib/snmp_walk.py
index 21b8a99..0d68c2c 100644
--- a/Reconnoitre/lib/snmp_walk.py
+++ b/Reconnoitre/lib/snmp_walk.py
@@ -1,83 +1,73 @@
+#!/usr/bin/python
+from Reconnoitre.lib.subprocess_helper import run_scan
+from Reconnoitre.lib.file_helper import FileHelper
 import multiprocessing
 import socket
 import subprocess
 
-from Reconnoitre.lib.file_helper import check_directory, load_targets
-from Reconnoitre.lib.subprocess_helper import run_scan
-
-
-def valid_ip(address):
-    try:
-        socket.inet_aton(address)
-        return True
-    except socket.error:
-        return False
-
-
-def target_file(target_hosts, output_directory, quiet):
-    targets = load_targets(target_hosts, output_directory, quiet)
-    target_file = open(targets, 'r')
-    try:
-        target_file = open(targets, 'r')
-        print("[*] Loaded targets from: %s" % targets)
-    except Exception:
-        print("[!] Unable to load: %s" % targets)
-
-    for ip_address in target_file:
-        ip_address = ip_address.strip()
-
-        snmp_directory = output_directory + '/' + ip_address + '/scans/snmp/'
-        check_directory(snmp_directory)
 
+class SnmpWalk(object):
+
+    def __init__(
+            self,
+            target_hosts,
+            output_directory,
+            quiet):
+
+        self.target_hosts = target_hosts
+        self.output_directory = output_directory
+        self.quiet = quiet
+        self.snmp_directory = f"{self.output_directory}/{self.target_hosts}/scans/snmp/"
+
+    @staticmethod
+    def valid_ip(address):
+        try:
+            socket.inet_aton(address)
+            return True
+        except socket.error:
+            return False
+
+    def target_file(self):
+        targets = FileHelper.load_targets(self.target_hosts, self.output_directory, self.quiet)
+        FileHelper.check_file(targets)
+
+        try:
+            target_file = open(targets, 'r')
+            print(f"[*] Loaded targets from: {targets}")
+        except FileNotFoundError as err:
+            print(f"[!] Unable to load: {targets}")
+            raise err
+
+        for ip_address in target_file:
+            ip_address = ip_address.strip()
+            snmp_directory = f"{self.output_directory}/{ip_address}/scans/snmp/"
+            FileHelper.check_directory(output_directory=snmp_directory)
+
+            jobs = []
+            p = multiprocessing.Process(target=SnmpWalk.snmp_scans)
+            jobs.append(p)
+            p.start()
+        target_file.close()
+
+    def target_ip(self):
+        print(f"[*] Loaded single target: {self.target_hosts}")
+        FileHelper.check_directory(output_directory=self.snmp_directory)
         jobs = []
-        p = multiprocessing.Process(
-            target=snmp_scans, args=(
-                ip_address, snmp_directory))
+        p = multiprocessing.Process(target=SnmpWalk.snmp_scans)
         jobs.append(p)
         p.start()
-    target_file.close()
 
+    def snmp_walk(self):
+        FileHelper.check_directory(output_directory=self.output_directory)
 
-def target_ip(target_hosts, output_directory, quiet):
-    print("[*] Loaded single target: %s" % target_hosts)
-    target_hosts = target_hosts.strip()
+        if (self.valid_ip(self.target_hosts)):
+            self.target_ip()
+        else:
+            self.target_file()
 
-    snmp_directory = output_directory + '/' + target_hosts + '/scans/snmp/'
-    check_directory(snmp_directory)
-
-    jobs = []
-    p = multiprocessing.Process(
-        target=snmp_scans, args=(
-            target_hosts, snmp_directory))
-    jobs.append(p)
-    p.start()
-
-
-def snmp_walk(target_hosts, output_directory, quiet):
-    check_directory(output_directory)
-
-    if (valid_ip(target_hosts)):
-        target_ip(target_hosts, output_directory, quiet)
-    else:
-        target_file(target_hosts, output_directory, quiet)
-
-
-def snmp_scans(ip_address, output_directory):
-    print("[+] Performing SNMP scans for %s to %s" %
-          (ip_address, output_directory))
-    print(
-        "   [>] Performing snmpwalk on public tree for:"
-        " %s - Checking for System Processes" %
-        (ip_address))
-    SCAN = ("snmpwalk -c public -v1 %s "
-            "1.3.6.1.2.1.25.1.6.0 > '%s%s-systemprocesses.txt'" % (
-                ip_address, output_directory, ip_address))
-
-    try:
+    def snmp_scans(self):
+        print(f"[+] Performing SNMP scans for {self.target_hosts} to {self.output_directory}")
+        print(f"\t[>] Performing snmpwalk on public tree for: {self.target_hosts} - Checking for System Processes")
+        SCAN = (f"snmpwalk -c public -v1 {self.target_hosts} 1.3.6.1.2.1.25.1.6.0 > '{self.output_directory}/{self.target_hosts}/systemprocesses.txt'")
         run_scan(SCAN, stderr=subprocess.STDOUT)
-    except Exception:
-        print("[+] No Response from %s" % ip_address)
-    except subprocess.CalledProcessError:
-        print("[+] Subprocess failure during scan of %s" % ip_address)
-
-    print("[+] Completed SNMP scans for %s" % (ip_address))
+        print("[+] Completed SNMP scans for %s" % (self.target_hosts))
diff --git a/Reconnoitre/lib/subprocess_helper.py b/Reconnoitre/lib/subprocess_helper.py
index 992cab0..ca425e3 100644
--- a/Reconnoitre/lib/subprocess_helper.py
+++ b/Reconnoitre/lib/subprocess_helper.py
@@ -1,3 +1,5 @@
+#!/usr/bin/python
+from subprocess import CalledProcessError
 import subprocess
 
 
@@ -5,4 +7,7 @@ def run_scan(scan, stderr=None):
     """Helper method to perform a scan using a subprocess and return results.
     We use the same configuration options for each call to check_output, this
     can be bunched into one helper function to keep config constant."""
-    return subprocess.check_output(scan, shell=True, stderr=stderr, universal_newlines=True)
+    try:
+        return subprocess.check_output(scan, shell=True, stderr=stderr, universal_newlines=True)
+    except CalledProcessError as err:
+        raise err
diff --git a/Reconnoitre/reconnoitre.py b/Reconnoitre/reconnoitre.py
index 6d3d6df..505af9e 100644
--- a/Reconnoitre/reconnoitre.py
+++ b/Reconnoitre/reconnoitre.py
@@ -4,13 +4,13 @@
 import signal
 import sys
 
-from .lib.core.input import CliArgumentParser
-from .lib.find_dns import find_dns
-from .lib.hostname_scan import hostname_scan
-from .lib.ping_sweeper import ping_sweeper
-from .lib.service_scan import service_scan
-from .lib.snmp_walk import snmp_walk
-from .lib.virtual_host_scanner import VirtualHostScanner
+from Reconnoitre.lib.core.input import CliArgumentParser
+from Reconnoitre.lib.find_dns import FindDns
+from Reconnoitre.lib.hostname_scan import HostnameScan
+from Reconnoitre.lib.ping_sweeper import PingSweeper
+from Reconnoitre.lib.service_scan import ServiceScan
+from Reconnoitre.lib.snmp_walk import SnmpWalk
+from Reconnoitre.lib.virtual_host_scanner import VirtualHostScanner
 
 
 def print_banner():
@@ -29,7 +29,7 @@ def util_checks(util=None):
     if (pyvers[0] >= 3) and (pyvers[1] >= 3):  # python3.3+
         import shutil
         if shutil.which(util) is None:
-            if util is "nmap":
+            if util == "nmap":
                 print(
                     "   [!] nmap was not found on your system."
                     " Exiting since we wont be able to scan anything. "
@@ -46,7 +46,7 @@ def util_checks(util=None):
     else:  # less-than python 3.3
         from distutils import spawn
         if spawn.find_executable(util) is None:
-            if util is "nmap":
+            if util == "nmap":
                 print(
                     "   [!] nmap was not found on your system."
                     " Exiting since we wont be able to scan anything. "
@@ -62,12 +62,9 @@ def util_checks(util=None):
             return "Found"
 
 
-def main():
-    parser = CliArgumentParser()
-    arguments = parser.parse(sys.argv[1:])
+def main(arguments):
     dns_servers = ''
 
-
     if arguments.output_directory.endswith('/' or '\\'):
         arguments.output_directory = arguments.output_directory[:-1]
     if arguments.target_hosts.endswith('/' or '\\'):
@@ -84,41 +81,46 @@ def main():
 
     if arguments.ping_sweep is True:
         print("[#] Performing ping sweep")
-        ping_sweeper(
+        scanner = PingSweeper(
             arguments.target_hosts,
             arguments.output_directory,
             arguments.quiet)
+        scanner.ping_sweeper()
 
     if arguments.hostname_scan is True:
         print("[#] Identifying hostnames")
-        hostname_scan(
+        scanner = HostnameScan(
             arguments.target_hosts,
             arguments.output_directory,
             arguments.quiet)
+        scanner.hostname_scan()
 
     if arguments.find_dns_servers is True:
         print("[#] Identifying DNS Servers")
-        dns_servers = find_dns(
+        scanner = FindDns(
             arguments.target_hosts,
             arguments.output_directory,
             arguments.quiet)
+        dns_servers = scanner.find_dns()
 
     if arguments.perform_service_scan is True:
         print("[#] Performing service scans")
-        service_scan(
+        scanner = ServiceScan(
             arguments.target_hosts,
             arguments.output_directory,
             dns_servers,
             arguments.quiet,
             arguments.quick,
             arguments.no_udp_service_scan)
+        scanner.service_scan()
 
     if arguments.perform_snmp_walk is True:
         print("[#] Performing SNMP walks")
-        snmp_walk(
+        scanner = SnmpWalk(
             arguments.target_hosts,
             arguments.output_directory,
             arguments.quiet)
+        scanner.snmp_walk()
 
     if arguments.virtualhosts is True:
         print("[#] Performing Virtual host scans")
@@ -145,4 +147,6 @@ def signal_handler(signal, frame):
 
 
 if __name__ == "__main__":
-    main()
+    parser = CliArgumentParser()
+    args = parser.parse(sys.argv[1:])
+    main(args)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/sample.nmap b/tests/sample.nmap
index 13121d4..4af9ae5 100644
--- a/tests/sample.nmap
+++ b/tests/sample.nmap
@@ -1,9 +1,18 @@
-# Nmap 7.50 scan initiated Sat Sep  2 07:12:47 2017 as: nmap -Pn -n -oN /sample.nmap 10.10.10.18
-Nmap scan report for 10.10.10.18
-Host is up (0.33s latency).
-Not shown: 998 closed ports
-PORT   STATE SERVICE
-22/tcp open  ssh
-80/tcp open  http
+# Nmap 7.80 scan initiated Sat Jun 27 15:54:26 2020 as: nmap -sC -sV -Pn --disable-arp-ping -oA /home/ben/Desktop/34.94.3.143/scans/34.94.3.143.quick 34.94.3.143
+Nmap scan report for 143.3.94.34.bc.googleusercontent.com (34.94.3.143)
+Host is up (0.060s latency).
+Not shown: 997 filtered ports
+PORT     STATE  SERVICE       VERSION
+22/tcp   open   ssh           OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
+| ssh-hostkey:
+|   2048 fc:4c:60:8c:ed:13:eb:21:90:72:e1:2b:96:60:fb:6e (RSA)
+|   256 d9:cb:07:30:e2:eb:2d:67:d5:c6:7c:55:f1:f4:7e:34 (ECDSA)
+|_  256 73:e8:91:5d:f8:8e:f7:57:f6:99:b2:3c:77:aa:0b:f9 (ED25519)
+80/tcp   open   http          nginx 1.14.0 (Ubuntu)
+|_http-server-header: nginx/1.14.0 (Ubuntu)
+|_http-title: Welcome to nginx!
+5001/tcp closed commplex-link
+Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
 
-# Nmap done at Sat Sep  2 07:14:22 2017 -- 1 IP address (1 host up) scanned in 95.38 seconds
+Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
+# Nmap done at Sat Jun 27 15:54:41 2020 -- 1 IP address (1 host up) scanned in 14.83 seconds
diff --git a/tests/test_file_helper.py b/tests/test_file_helper.py
new file mode 100644
index 0000000..7ece1fa
--- /dev/null
+++ b/tests/test_file_helper.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+from unittest import TestCase
+from Reconnoitre.lib.file_helper import FileHelper
+import os
+
+
+class TestFileHelper(TestCase):
+
+    HOST = "34.94.3.143"
+    IP_RANGE = "34.94.3.0-143"
+    OUTPUT_DIR = os.path.join("results")
+    OUTPUT_FILE = os.path.join("results", "targets.txt")
+    INVALID_DIR = os.path.join("results", "InvalidDirectory")
+    NEW_DIR = os.path.join("results", "NewDirectory")
+    SAMPLE_NMAP = os.path.join('sample.nmap')
+
+    def test_check_directory(self):
+        res = FileHelper.check_directory(output_directory=self.OUTPUT_DIR)
+        self.assertIsNotNone(res)
+        self.assertTrue(os.path.exists(res))
+        self.assertTrue(os.path.isdir(res))
+        self.assertFalse(os.path.exists(self.INVALID_DIR))
+        res2 = FileHelper.check_directory(output_directory=self.INVALID_DIR)
+        self.assertTrue(os.path.exists(res2))
+        self.assertTrue(os.path.isdir(res2))
+        os.rmdir(res2)
+
+    def test_make_directory(self):
+        if os.path.exists(self.NEW_DIR):
+            os.rmdir(self.NEW_DIR)
+
+        FileHelper.make_directory(output_directory=self.NEW_DIR)
+        self.assertTrue(os.path.exists(self.NEW_DIR))
+        self.assertTrue(os.path.isdir(self.NEW_DIR))
+        self.assertRaises(FileExistsError, FileHelper.make_directory, output_directory=self.NEW_DIR)
+        os.rmdir(self.NEW_DIR)
+
+    def test_check_file(self):
+        res = FileHelper.check_file(self.OUTPUT_FILE)
+        self.assertIsNotNone(res)
+        self.assertTrue(os.path.exists(res))
+        self.assertTrue(os.path.isfile(res))
+        os.remove(self.OUTPUT_FILE)
+
+    def test_make_file(self):
+        if os.path.exists(self.OUTPUT_FILE):
+            os.remove(self.OUTPUT_FILE)
+
+        FileHelper.make_file(self.OUTPUT_FILE)
+        self.assertIsNotNone(self.OUTPUT_FILE)
+        self.assertTrue(os.path.exists(self.OUTPUT_FILE))
+        self.assertTrue(os.path.isfile(self.OUTPUT_FILE))
+        os.remove(self.OUTPUT_FILE)
+
+    def test_load_targets(self):
+        res = FileHelper.load_targets(target_hosts=self.HOST, output_directory=self.OUTPUT_DIR, quiet=False)
+        self.assertEqual(res, f'{self.OUTPUT_DIR}/targets.txt')
+
+    def test_expand_targets(self):
+
+        FileHelper.expand_targets(target_hosts=self.IP_RANGE, output_directory=self.OUTPUT_DIR)
+        self.assertTrue(os.path.exists(f'{self.OUTPUT_DIR}/targets.txt'))
+        self.assertTrue(os.path.isfile(f'{self.OUTPUT_DIR}/targets.txt'))
+        os.remove(f'{self.OUTPUT_DIR}/targets.txt')
+
+    def test_create_dir_structure(self):
+        FileHelper.create_dir_structure(ip_address=self.HOST, output_directory=self.OUTPUT_DIR)
+        res_dir = f'{self.OUTPUT_DIR}/{self.HOST}'
+        self.assertTrue(os.path.exists(res_dir))
+        self.assertTrue(os.path.isdir(res_dir))
+        self.assertTrue(os.path.exists(f'{res_dir}/proof.txt'))
+        self.assertTrue(os.path.isfile(f'{res_dir}/proof.txt'))
+        self.assertTrue(os.path.exists(f'{res_dir}/exploit'))
+        self.assertTrue(os.path.isdir(f'{res_dir}/exploit'))
+        self.assertTrue(os.path.exists(f'{res_dir}/loot'))
+        self.assertTrue(os.path.isdir(f'{res_dir}/loot'))
+        self.assertTrue(os.path.exists(f'{res_dir}/scans'))
+        self.assertTrue(os.path.isdir(f'{res_dir}/scans'))
+
+        # remove the added directories
+        os.remove(f'{res_dir}/proof.txt')
+        os.rmdir(f'{res_dir}/exploit/')
+        os.rmdir(f'{res_dir}/loot/')
+        os.rmdir(f'{res_dir}/scans/')
+        os.rmdir(f'{res_dir}/')
+
+    def test_write_recommendations(self):
+        FileHelper.write_recommendations(results=self.SAMPLE_NMAP, ip_address=self.HOST, outputdir=self.OUTPUT_DIR)
+        res_dir = f'{self.OUTPUT_DIR}/{self.HOST}'
+        self.assertTrue(os.path.exists(f'{res_dir}_findings.txt'))
+        os.remove(f'{res_dir}_findings.txt')
+
+    def test_get_config_options(self):
+        flags = ['nmap', 'quickscan']
+        res = FileHelper.get_config_options(*flags)
+        self.assertIsNotNone(res)
+        self.assertEqual(res, '-sC -sV -Pn --disable-arp-ping')
diff --git a/tests/test_find_dns.py b/tests/test_find_dns.py
new file mode 100644
index 0000000..2a8cf9d
--- /dev/null
+++ b/tests/test_find_dns.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+from unittest import TestCase
+from Reconnoitre.lib.find_dns import FindDns
+import os
+
+
+class TestFindDns(TestCase):
+    HOST = "35.227.24.107"
+    OUTPUT_DIR = "results"
+    OUTPUT_FILE = f"{OUTPUT_DIR}/targets.txt"
+    OUTPUT_DETAILS = f"{OUTPUT_DIR}/DNS-Detailed.txt"
+    OUTPUT_TARGETS = f"{OUTPUT_DIR}/DNS-targets.txt"
+    F = FindDns(target_hosts=HOST, output_directory=OUTPUT_DIR, quiet=False)
+
+    def test_find_dns(self):
+        res = self.F.find_dns()
+        self.assertIsNotNone(res)
+        self.assertTrue(os.path.exists(self.OUTPUT_FILE))
+        self.assertTrue(os.path.exists(self.OUTPUT_DETAILS))
+        self.assertTrue(os.path.exists(self.OUTPUT_TARGETS))
+        os.remove(self.OUTPUT_FILE)
+        os.remove(self.OUTPUT_DETAILS)
+        os.remove(self.OUTPUT_TARGETS)
diff --git a/tests/test_hostname_scan.py b/tests/test_hostname_scan.py
new file mode 100644
index 0000000..56d432e
--- /dev/null
+++ b/tests/test_hostname_scan.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+from unittest import TestCase
+from Reconnoitre.lib.hostname_scan import HostnameScan
+import os
+
+class TestHostnameScan(TestCase):
+    HOST = "192.168.1.0/24"
+    OUTPUT_DIR = "results"
+    OUTPUT_FILE = f"{OUTPUT_DIR}/hostnames.txt"
+    H = HostnameScan(target_hosts=HOST, output_directory=OUTPUT_DIR, quiet=False)
+
+    def test_hostname_scan(self):
+        self.H.hostname_scan()
+        self.assertTrue(os.path.exists(self.OUTPUT_FILE))
+        self.assertTrue(os.path.isfile(self.OUTPUT_FILE))
+        os.remove(self.OUTPUT_FILE)
+
diff --git a/tests/test_ping_sweeper.py b/tests/test_ping_sweeper.py
new file mode 100644
index 0000000..1779437
--- /dev/null
+++ b/tests/test_ping_sweeper.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+from unittest import TestCase
+from Reconnoitre.lib.ping_sweeper import PingSweeper
+import os
+
+
+class TestPingSweep(TestCase):
+    """TODO: Add more tests covering unhappy paths"""
+
+    HOST = "34.94.3.143"
+    OUTPUT_DIR = "results"
+    OUTPUT_FILE = f"{OUTPUT_DIR}/test-live-hosts.txt"
+    PS = PingSweeper(target_hosts=HOST, output_directory=OUTPUT_DIR, quiet=False)
+
+    TEST_LINES = """
+    # Nmap 7.80 scan initiated Sat Jun 27 15:54:26 2020 as: nmap -sC -sV -Pn --disable-arp-ping -oA /home/ben/Desktop/34.94.3.143/scans/34.94.3.143.quick 34.94.3.143
+    Nmap scan report for 143.3.94.34.bc.googleusercontent.com (34.94.3.143)
+    Host is up (0.060s latency).
+    Not shown: 997 filtered ports
+    PORT     STATE  SERVICE       VERSION
+    22/tcp   open   ssh           OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
+    | ssh-hostkey:
+    |   2048 fc:4c:60:8c:ed:13:eb:21:90:72:e1:2b:96:60:fb:6e (RSA)
+    |   256 d9:cb:07:30:e2:eb:2d:67:d5:c6:7c:55:f1:f4:7e:34 (ECDSA)
+    |_  256 73:e8:91:5d:f8:8e:f7:57:f6:99:b2:3c:77:aa:0b:f9 (ED25519)
+    80/tcp   open   http          nginx 1.14.0 (Ubuntu)
+    |_http-server-header: nginx/1.14.0 (Ubuntu)
+    |_http-title: Welcome to nginx!
+    5001/tcp closed commplex-link
+    Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
+    
+    Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
+    # Nmap done at Sat Jun 27 15:54:41 2020 -- 1 IP address (1 host up) scanned in 14.83 seconds
+    """
+
+    def test_ping_sweeper(self):
+        self.PS.ping_sweeper()
+        self.assertTrue(os.path.exists(f"{self.OUTPUT_DIR}/targets.txt"))
+
+    def test_call_nmap_sweep(self):
+        self.PS.call_nmap_sweep()
+        self.assertTrue(self.HOST in "\n".join(self.PS.nmap_lines))
+
+    def test_parse_nmap_output_for_live_hosts(self):
+        self.PS.parse_nmap_output_for_live_hosts()
+        self.assertIsInstance(self.PS.live_hosts, list)
+
+    def test_write_live_hosts_list_to_file(self):
+        self.PS.ping_sweeper()
+        self.PS.write_live_hosts_list_to_file()
+        self.assertTrue(os.path.exists(self.PS.output_file))
+        os.remove(self.PS.output_file)
diff --git a/tests/test_service_scan.py b/tests/test_service_scan.py
new file mode 100644
index 0000000..41fef89
--- /dev/null
+++ b/tests/test_service_scan.py
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+from unittest import TestCase
+from Reconnoitre.lib.service_scan import ServiceScan
+import os
+
+
+class TestServiceScan(TestCase):
+
+    IP_ADDR = '34.94.3.143'
+    OUTPUT_DIR = 'results'
+    DNS_SERVER = ''
+    QUIET = False
+    QUICK = False
+    no_udp_service_scan = True
+    sscan = ServiceScan(IP_ADDR, OUTPUT_DIR, DNS_SERVER, QUIET, QUICK, no_udp_service_scan)
+
+    def test_valid_ip(self):
+        self.assertTrue(self.sscan.valid_ip(self.IP_ADDR))
diff --git a/tests/test_snmp_walk.py b/tests/test_snmp_walk.py
new file mode 100644
index 0000000..5a76800
--- /dev/null
+++ b/tests/test_snmp_walk.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+from Reconnoitre.lib.snmp_walk import SnmpWalk
+from unittest import TestCase
+import os
+
+
+class TestSnmpWalk(TestCase):
+    HOST = "34.94.3.143"
+    OUTPUT_DIR = "results"
+    SNMP_DIR = f"{OUTPUT_DIR}/{HOST}/scans/snmp/"
+    sw = SnmpWalk(HOST, OUTPUT_DIR, False)
+
+    def test_valid_ip(self):
+        self.assertTrue(self.sw.valid_ip(self.HOST))
diff --git a/tests/validate_config.py b/tests/validate_config.py
index 29d4c07..c2d6192 100644
--- a/tests/validate_config.py
+++ b/tests/validate_config.py
@@ -3,7 +3,7 @@
 from argparse import ArgumentParser
 import json
 
-from reconnoitre import print_banner
+from Reconnoitre.reconnoitre import print_banner
 
 CONFIG = '../reconnoitre/config.json'
 SOURCEFILE = './sample.nmap'