diff --git a/tests/run.yml b/tests/run.yml
index c8df10e73ab8ade2a53cdddfbcbe90647bd65742..f9190b0ee1fa5e5f33e17de8a4a74476be91da1a 100644
--- a/tests/run.yml
+++ b/tests/run.yml
@@ -26,6 +26,12 @@
         upper_constraints_file: "{{ ansible_env.HOME }}/src/opendev.org/openstack/requirements/upper-constraints.txt"
         docker_image_tag_suffix: "{{ '-aarch64' if ansible_architecture == 'aarch64' else '' }}"
 
+    - name: Install dig for Designate testing
+      become: true
+      package:
+        name: "{{ 'bind-utils' if ansible_os_family == 'RedHat' else 'dnsutils' }}"
+      when: scenario == 'magnum'
+
     - name: Install xfsprogs package for Swift filesystems
       become: true
       package:
@@ -384,7 +390,7 @@
             EXT_NET_LOCAL_ADDR: "{{ neutron_external_network_prefix }}1/{{ neutron_external_network_prefix_length }}"
             EXT_NET_SLAVE_DEVICE: "{{ neutron_external_interface_name }}"
             SCENARIO: "{{ scenario }}"
-          when: openstack_core_tested or scenario in ['ironic', 'scenario_nfv', 'zun']
+          when: openstack_core_tested or scenario in ['ironic', 'magnum', 'scenario_nfv', 'zun']
 
         - name: Run test-core-openstack.sh script
           script:
diff --git a/tests/setup_gate.sh b/tests/setup_gate.sh
index c1d505fdcf73077645f493c4adff252513ba20b3..26d4f279e26711b6c02b816be1cd7f476332d5a9 100755
--- a/tests/setup_gate.sh
+++ b/tests/setup_gate.sh
@@ -18,7 +18,7 @@ function setup_openstack_clients {
         packages+=(python-ironicclient python-ironic-inspector-client)
     fi
     if [[ $SCENARIO == magnum ]]; then
-        packages+=(python-magnumclient python-octaviaclient)
+        packages+=(python-designateclient python-magnumclient python-octaviaclient)
     fi
     if [[ $SCENARIO == masakari ]]; then
         packages+=(python-masakariclient)
@@ -63,7 +63,7 @@ function prepare_images {
         GATE_IMAGES+=",^dnsmasq,^ironic,^iscsid"
     fi
     if [[ $SCENARIO == "magnum" ]]; then
-        GATE_IMAGES+=",^magnum,^octavia"
+        GATE_IMAGES+=",^designate,^magnum,^octavia"
     fi
     if [[ $SCENARIO == "masakari" ]]; then
         GATE_IMAGES+=",^masakari"
diff --git a/tests/templates/globals-default.j2 b/tests/templates/globals-default.j2
index bf4364d913bac9c73fcce118a51a65d4cf59883d..a5400612f0b5339ee8bd2018d6ce269bcbb2c17c 100644
--- a/tests/templates/globals-default.j2
+++ b/tests/templates/globals-default.j2
@@ -154,6 +154,7 @@ enable_prometheus_openstack_exporter: "no"
 {% endif %}
 
 {% if scenario == "magnum" %}
+enable_designate: "yes"
 enable_magnum: "yes"
 enable_octavia: "yes"
 {% endif %}
diff --git a/tests/test-magnum.sh b/tests/test-magnum.sh
index 9519fba25795c2e4fec7b0ab12048ad015fadb5c..bd43dd9451217e4c6713e3eaeafc7c3d1c854459 100755
--- a/tests/test-magnum.sh
+++ b/tests/test-magnum.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Test deployment of magnum and octavia.
+# Test deployment of magnum, octavia and designate.
 
 set -o xtrace
 set -o errexit
@@ -18,21 +18,60 @@ function test_octavia {
     openstack loadbalancer list
 }
 
+function test_designate {
+    # Smoke test.
+    openstack zone list --all
+
+    # Create a default zone for fixed and floating IPs, then reconfigure nova
+    # and neutron to use it.
+    openstack zone create --email admin@example.org example.org.
+    ZONE_ID=$(openstack zone show example.org. -f value -c id)
+
+    mkdir -p /etc/kolla/config/designate/
+    cat << EOF > /etc/kolla/config/designate/designate-sink.conf
+[handler:nova_fixed]
+zone_id = ${ZONE_ID}
+[handler:neutron_floatingip]
+zone_id = ${ZONE_ID}
+EOF
+
+    RAW_INVENTORY=/etc/kolla/inventory
+    kolla-ansible -i ${RAW_INVENTORY} --tags designate -vvv reconfigure &> /tmp/logs/ansible/reconfigure-designate
+
+    # Create an instance, and check that its name resolves.
+    openstack server create --wait --image cirros --flavor m1.tiny --key-name mykey --network demo-net dns-test --wait
+    attempt=1
+    while true; do
+        IP=$(dig +short @192.0.2.1 dns-test.example.org. A)
+        if [[ -n $IP ]]; then
+            break
+        fi
+        attempt=$((attempt+1))
+        if [[ $attempt -eq 10 ]]; then
+            echo "Failed to resolve dns-test.example.org."
+            openstack recordset list ${ZONE_ID}
+            exit 1
+        fi
+        sleep 10
+    done
+}
+
 function test_magnum_logged {
     . /etc/kolla/admin-openrc.sh
     . ~/openstackclient-venv/bin/activate
     test_magnum_clusters
     test_octavia
+    test_designate
 }
 
 function test_magnum {
-    echo "Testing Magnum and Octavia"
+    echo "Testing Magnum, Octavia and Designate"
     test_magnum_logged > /tmp/logs/ansible/test-magnum 2>&1
     result=$?
     if [[ $result != 0 ]]; then
-        echo "Testing Magnum and Octavia failed. See ansible/test-magnum for details"
+        echo "Testing Magnum, Octavia and Designate failed. See ansible/test-magnum for details"
     else
-        echo "Successfully tested Magnum and Octavia. See ansible/test-magnum for details"
+        echo "Successfully tested Magnum, Octavia and Designate . See ansible/test-magnum for details"
     fi
     return $result
 }
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index 42dad4884cef7b556f39a7592763998af068c326..87760c25e2494117cc09925d245fbbc70bddc858 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -131,7 +131,7 @@
     parent: kolla-ansible-base
     voting: false
     files:
-      - ^ansible/roles/(magnum|octavia)/
+      - ^ansible/roles/(designate|magnum|octavia)/
       - ^tests/test-dashboard.sh
       - ^tests/test-magnum.sh
     vars: