diff --git a/autotests/testAP/connection_test.py b/autotests/testAP/connection_test.py
index 02213947..273c333c 100644
--- a/autotests/testAP/connection_test.py
+++ b/autotests/testAP/connection_test.py
@@ -1,90 +1,24 @@
 #! /usr/bin/python3
 
 import unittest
-import sys, os
 
-import iwd
 from iwd import IWD
-from iwd import PSKAgent
-from iwd import NetworkType
-from hostapd import HostapdCLI
-import testutil
+from validation import validate, client_connect
 
 class Test(unittest.TestCase):
-
-    def client_connect(self, wd, dev):
-        hostapd = HostapdCLI(config='psk-ccmp.conf')
-
-        ordered_network = dev.get_ordered_network('TestAP1')
-
-        self.assertEqual(ordered_network.type, NetworkType.psk)
-
-        psk_agent = PSKAgent('Password1')
-        wd.register_psk_agent(psk_agent)
-
-        ordered_network.network_object.connect()
-
-        condition = 'obj.state == DeviceState.connected'
-        wd.wait_for_object_condition(dev, condition)
-
-        wd.unregister_psk_agent(psk_agent)
-
-        testutil.test_iface_operstate(dev.name)
-        testutil.test_ifaces_connected(hostapd.ifname, dev.name)
-
-        dev.disconnect()
-
-        condition = 'not obj.connected'
-        wd.wait_for_object_condition(ordered_network.network_object, condition)
-
     def test_connection_success(self):
         wd = IWD(True)
 
         dev1, dev2 = wd.list_devices(2)
 
-        self.client_connect(wd, dev1)
+        client_connect(wd, dev1, 'TestAP1')
 
         dev1.start_ap('TestAP2', 'Password2')
 
-        try:
-            networks = {}
-            networks['TestAP1'] = dev2.get_ordered_network('TestAP1', full_scan=True)
-            networks['TestAP2'] = dev2.get_ordered_network('TestAP2', full_scan=True)
-
-            self.assertEqual(networks['TestAP1'].type, NetworkType.psk)
-            self.assertEqual(networks['TestAP2'].type, NetworkType.psk)
-
-            psk_agent = PSKAgent('Password2')
-            wd.register_psk_agent(psk_agent)
-
-            try:
-                dev2.disconnect()
-
-                condition = 'not obj.connected'
-                wd.wait_for_object_condition(dev2, condition)
-            except:
-                pass
-
-            networks['TestAP2'].network_object.connect()
-
-            condition = 'obj.state == DeviceState.connected'
-            wd.wait_for_object_condition(dev2, condition)
-
-            testutil.test_iface_operstate(dev2.name)
-            testutil.test_ifaces_connected(dev1.name, dev2.name, group=False)
-
-            wd.unregister_psk_agent(psk_agent)
-
-            dev2.disconnect()
-
-            condition = 'not obj.connected'
-            wd.wait_for_object_condition(networks['TestAP2'].network_object,
-                                         condition)
-        finally:
-            dev1.stop_ap()
+        validate(wd, dev2, dev1, 'TestAP2', 'Password2')
 
         # Finally test dev1 can go to client mode and connect again
-        self.client_connect(wd, dev1)
+        client_connect(wd, dev1, 'TestAP1')
 
     @classmethod
     def setUpClass(cls):
diff --git a/autotests/testAP/dhcp_config_test.py b/autotests/testAP/dhcp_config_test.py
index ac3a95ba..2c75d071 100644
--- a/autotests/testAP/dhcp_config_test.py
+++ b/autotests/testAP/dhcp_config_test.py
@@ -1,14 +1,10 @@
 #! /usr/bin/python3
 
 import unittest
-import sys, os
 
-import iwd
 from iwd import IWD
-from iwd import PSKAgent
-from iwd import NetworkType
 from config import ctx
-import testutil
+from validation import validate
 
 class Test(unittest.TestCase):
     def test_connection_success(self):
@@ -28,47 +24,8 @@ class Test(unittest.TestCase):
 
         dev1.start_ap('APConfig')
 
-        try:
-            networks = {}
-            networks['APConfig'] = dev2.get_ordered_network('APConfig', full_scan=True)
-
-            self.assertEqual(networks['APConfig'].type, NetworkType.psk)
-
-            psk_agent = PSKAgent('password123')
-            wd.register_psk_agent(psk_agent)
-
-            try:
-                dev2.disconnect()
-
-                condition = 'not obj.connected'
-                wd.wait_for_object_condition(dev2, condition)
-            except:
-                pass
-
-            networks['APConfig'].network_object.connect()
-
-            condition = 'obj.state == DeviceState.connected'
-            wd.wait_for_object_condition(dev2, condition)
-
-            testutil.test_iface_operstate(dev2.name)
-            #
-            # TODO: cannot yet check the AP interface IP since its in a
-            #       different namespace.
-            #
-            testutil.test_ip_address_match(dev2.name, "192.168.1.3")
-
-            testutil.test_ip_connected(('192.168.1.3', ctx), ('192.168.1.1', ns0))
-
-            wd.unregister_psk_agent(psk_agent)
-
-            dev2.disconnect()
-
-            condition = 'not obj.connected'
-            wd.wait_for_object_condition(networks['APConfig'].network_object,
-                                         condition)
-
-        finally:
-            dev1.stop_ap()
+        validate(wd, dev2, dev1, 'APConfig', 'password123',
+                    sta_ip_info=('192.168.1.3', ctx), ap_ip_info=('192.168.1.1', ns0))
 
     @classmethod
     def setUpClass(cls):
diff --git a/autotests/testAP/dhcp_test.py b/autotests/testAP/dhcp_test.py
index a8f89eb0..aa50fdb4 100644
--- a/autotests/testAP/dhcp_test.py
+++ b/autotests/testAP/dhcp_test.py
@@ -10,6 +10,8 @@ from iwd import NetworkType
 from config import ctx
 import testutil
 
+from validation import validate
+
 class Test(unittest.TestCase):
     def test_connection_success(self):
         wd = IWD(True, '/tmp/dhcp')
@@ -25,59 +27,36 @@ class Test(unittest.TestCase):
         with self.assertRaises(iwd.AlreadyExistsEx):
             dev4.start_ap('TestAP4', 'Password4')
 
-        try:
-            networks = {}
-            networks['TestAP2'] = dev2.get_ordered_network('TestAP2', full_scan=True)
-
-            self.assertEqual(networks['TestAP2'].type, NetworkType.psk)
-
-            psk_agent = PSKAgent('Password2')
-            wd.register_psk_agent(psk_agent)
-
-            try:
-                dev2.disconnect()
-
-                condition = 'not obj.connected'
-                wd.wait_for_object_condition(dev2, condition)
-            except:
-                pass
+        validate(wd, dev2, dev1, 'TestAP2', 'Password2', ip_checks=False)
 
-            networks['TestAP2'].network_object.connect()
+        network = dev2.get_ordered_network('TestAP2', full_scan=True)
 
-            condition = 'obj.state == DeviceState.connected'
-            wd.wait_for_object_condition(dev2, condition)
-
-            testutil.test_iface_operstate(dev2.name)
-            testutil.test_ifaces_connected(dev1.name, dev2.name, group=False)
-
-            try:
-                testutil.test_ip_address_match(dev1.name, "192.168.80.1")
-                testutil.test_ip_address_match(dev2.name, "192.168.80.2")
-                ip = "192.168.80.1"
-            except:
-                testutil.test_ip_address_match(dev1.name, "192.168.80.17")
-                testutil.test_ip_address_match(dev2.name, "192.168.80.18")
-                ip = "192.168.80.17"
-
-            wd.unregister_psk_agent(psk_agent)
+        try:
+            testutil.test_ip_address_match(dev1.name, "192.168.80.1")
+            testutil.test_ip_address_match(dev2.name, "192.168.80.2")
+            ip = "192.168.80.1"
+        except:
+            testutil.test_ip_address_match(dev1.name, "192.168.80.17")
+            testutil.test_ip_address_match(dev2.name, "192.168.80.18")
+            ip = "192.168.80.17"
 
-            dev2.disconnect()
+        dev2.disconnect()
 
-            condition = 'not obj.connected'
-            wd.wait_for_object_condition(networks['TestAP2'].network_object,
-                                         condition)
+        condition = 'not obj.connected'
+        wd.wait_for_object_condition(network.network_object, condition)
 
-            # This should release the IP */
-            dev1.stop_ap()
+        # This should release the IP */
+        dev1.stop_ap()
 
-            # This should now succeed and the IP should match the old IP dev1
-            # got initially.
-            dev4.start_ap('TestAP4', 'Password4')
+        # This should now succeed and the IP should match the old IP dev1
+        # got initially.
+        dev4.start_ap('TestAP4', 'Password4')
 
-            testutil.test_ip_address_match(dev4.name, ip)
+        testutil.test_ip_address_match(dev4.name, ip)
 
-        finally:
-            dev1.stop_ap()
+        dev1.stop_ap()
+        dev3.stop_ap()
+        dev4.stop_ap()
 
     @classmethod
     def setUpClass(cls):
diff --git a/autotests/testAP/validation.py b/autotests/testAP/validation.py
new file mode 100644
index 00000000..b1b867ef
--- /dev/null
+++ b/autotests/testAP/validation.py
@@ -0,0 +1,71 @@
+from iwd import PSKAgent
+from iwd import NetworkType
+from hostapd import HostapdCLI
+import testutil
+
+def validate(wd, sta_dev, ap_dev, ssid, passphrase,
+                sta_ip_info=None, ap_ip_info=None, ip_checks=True):
+    try:
+        network = sta_dev.get_ordered_network(ssid, full_scan=True)
+
+        if network.type != NetworkType.psk:
+            raise Exception("Network type mismatch")
+
+        psk_agent = PSKAgent(passphrase)
+        wd.register_psk_agent(psk_agent)
+
+        network.network_object.connect()
+
+        condition = 'obj.state == DeviceState.connected'
+        wd.wait_for_object_condition(sta_dev, condition)
+
+        testutil.test_iface_operstate(sta_dev.name)
+
+        # This implies separate namespaces so the iface names won't exist
+        if not sta_ip_info or not ap_ip_info:
+            testutil.test_ifaces_connected(ap_dev.name, sta_dev.name, group=False)
+
+        if not ip_checks:
+            return
+
+        if sta_ip_info:
+            testutil.test_ip_address_match(sta_dev.name, sta_ip_info[0])
+
+        if sta_ip_info and ap_ip_info:
+            testutil.test_ip_connected(sta_ip_info, ap_ip_info)
+
+        wd.unregister_psk_agent(psk_agent)
+
+        sta_dev.disconnect()
+
+        condition = 'not obj.connected'
+        wd.wait_for_object_condition(network.network_object, condition)
+    finally:
+        if ip_checks:
+            ap_dev.stop_ap()
+
+def client_connect(wd, dev, ssid):
+    hostapd = HostapdCLI(config='psk-ccmp.conf')
+
+    ordered_network = dev.get_ordered_network(ssid)
+
+    if ordered_network.type != NetworkType.psk:
+        raise Exception("Network type mismatch")
+
+    psk_agent = PSKAgent('Password1')
+    wd.register_psk_agent(psk_agent)
+
+    ordered_network.network_object.connect()
+
+    condition = 'obj.state == DeviceState.connected'
+    wd.wait_for_object_condition(dev, condition)
+
+    wd.unregister_psk_agent(psk_agent)
+
+    testutil.test_iface_operstate(dev.name)
+    testutil.test_ifaces_connected(hostapd.ifname, dev.name)
+
+    dev.disconnect()
+
+    condition = 'not obj.connected'
+    wd.wait_for_object_condition(ordered_network.network_object, condition)
