diff --git a/meta/conf/distro/include/ptest-packagelists.inc b/meta/conf/distro/include/ptest-packagelists.inc
index bef45bb4d5..50b971bace 100644
--- a/meta/conf/distro/include/ptest-packagelists.inc
+++ b/meta/conf/distro/include/ptest-packagelists.inc
@@ -154,6 +154,7 @@ PTESTS_SLOW = "\
     python3-click \
     python3-cryptography \
     python3-numpy \
+    python3-uvloop \
     python3-xmltodict \
     strace \
     tar \
diff --git a/meta/recipes-devtools/python/python3-uvloop/run-ptest b/meta/recipes-devtools/python/python3-uvloop/run-ptest
new file mode 100755
index 0000000000..0cb9a26b88
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-uvloop/run-ptest
@@ -0,0 +1,50 @@
+#!/bin/sh
+# test_process_streams_redirect: replaces the stdout/stderr fds, which
+# conflicts with pytest's output capture.
+# test_process_preexec_fn_{1,2}, Test_UV_DNS test_getaddrinfo_{8,9}: libuv
+# 1.53.0 spawns with posix_spawn(), so preexec_fn never runs, and an empty
+# host gives EAI_NODATA.
+# test_getaddrinfo_{1,2,3,5,6,11}, Test_AIO_DNS test_getaddrinfo_{8,9}: each
+# DNS lookup waits for the resolver timeout without network access.
+# --deselect matches a node id prefix, so -k handles 1, 2 and 11.
+# riscv64: qemu runs without KVM there, too slow for the fixed timeouts in
+# the TLS stress tests, the issue39 deadlock check (signal.alarm(5)) and
+# test_socket_cancel_sock_sendall, which must cancel within 0.2s.
+SLOW=""
+if [ "$(uname -m)" = "riscv64" ]; then
+    SLOW="
+        --deselect=tests/test_tcp.py::Test_UV_TCPSSL::test_create_connection_ssl_1
+        --deselect=tests/test_tcp.py::Test_UV_TCPSSL::test_create_server_ssl_over_ssl
+        --deselect=tests/test_tcp.py::Test_UV_TCPSSL::test_renegotiation
+        --deselect=tests/test_tcp.py::Test_AIO_TCPSSL::test_create_connection_ssl_1
+        --deselect=tests/test_tcp.py::Test_AIO_TCPSSL::test_create_server_ssl_over_ssl
+        --deselect=tests/test_tcp.py::Test_AIO_TCPSSL::test_renegotiation
+        --deselect=tests/test_unix.py::Test_UV_UnixSSL::test_create_unix_connection_ssl_1
+        --deselect=tests/test_unix.py::Test_UV_UnixSSL::test_create_unix_server_ssl_1
+        --deselect=tests/test_unix.py::Test_AIO_UnixSSL::test_create_unix_connection_ssl_1
+        --deselect=tests/test_unix.py::Test_AIO_UnixSSL::test_create_unix_server_ssl_1
+        --deselect=tests/test_regr1.py::TestIssue39Regr::test_issue39_regression
+        --deselect=tests/test_sockets.py::TestUVSockets::test_socket_cancel_sock_sendall
+        --deselect=tests/test_sockets.py::TestAIOSockets::test_socket_cancel_sock_sendall
+    "
+fi
+KEEP="not (test_getaddrinfo_1 or test_getaddrinfo_2)"
+for n in 10 12 13 14 15 16 17 18 19 20 21 22; do
+    KEEP="$KEEP or test_getaddrinfo_$n"
+done
+pytest --automake $SLOW \
+    -k "$KEEP" \
+    --deselect=tests/test_process.py::Test_UV_Process::test_process_streams_redirect \
+    --deselect=tests/test_process.py::Test_AIO_Process::test_process_streams_redirect \
+    --deselect=tests/test_process.py::Test_UV_Process::test_process_preexec_fn_1 \
+    --deselect=tests/test_process.py::Test_UV_Process::test_process_preexec_fn_2 \
+    --deselect=tests/test_dns.py::Test_UV_DNS::test_getaddrinfo_3 \
+    --deselect=tests/test_dns.py::Test_UV_DNS::test_getaddrinfo_5 \
+    --deselect=tests/test_dns.py::Test_UV_DNS::test_getaddrinfo_6 \
+    --deselect=tests/test_dns.py::Test_UV_DNS::test_getaddrinfo_8 \
+    --deselect=tests/test_dns.py::Test_UV_DNS::test_getaddrinfo_9 \
+    --deselect=tests/test_dns.py::Test_AIO_DNS::test_getaddrinfo_3 \
+    --deselect=tests/test_dns.py::Test_AIO_DNS::test_getaddrinfo_5 \
+    --deselect=tests/test_dns.py::Test_AIO_DNS::test_getaddrinfo_6 \
+    --deselect=tests/test_dns.py::Test_AIO_DNS::test_getaddrinfo_8 \
+    --deselect=tests/test_dns.py::Test_AIO_DNS::test_getaddrinfo_9
diff --git a/meta/recipes-devtools/python/python3-uvloop_0.22.1.bb b/meta/recipes-devtools/python/python3-uvloop_0.22.1.bb
index 887c262ae7..39b6a2602a 100644
--- a/meta/recipes-devtools/python/python3-uvloop_0.22.1.bb
+++ b/meta/recipes-devtools/python/python3-uvloop_0.22.1.bb
@@ -7,11 +7,34 @@ LIC_FILES_CHKSUM = "file://LICENSE-APACHE;md5=bb92739ddad0a2811957bd98bdb90474 \
 
 DEPENDS += "libuv python3-wheel-native"
 
-SRC_URI += "file://0001-setup.cfg-use-system-libuv.patch"
+SRC_URI += "\
+    file://0001-setup.cfg-use-system-libuv.patch \
+    file://run-ptest \
+"
 SRC_URI[sha256sum] = "6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f"
 
-inherit pypi python_setuptools_build_meta cython
+inherit pypi python_setuptools_build_meta cython ptest-python-pytest
 
 RDEPENDS:${PN} = "python3-asyncio"
 
+RDEPENDS:${PN}-ptest += "\
+    python3-ctypes \
+    python3-io \
+    python3-logging \
+    python3-math \
+    python3-multiprocessing \
+    python3-netclient \
+    python3-numbers \
+    python3-pickle \
+    python3-pprint \
+    python3-psutil \
+    python3-pyopenssl \
+    python3-threading \
+"
+
+do_install_ptest:append() {
+    # test_sourcecode needs these to skip cleanly when flake8 and mypy are missing
+    install -m 0644 ${S}/.flake8 ${S}/mypy.ini ${D}${PTEST_PATH}/
+}
+
 BBCLASSEXTEND = "native nativesdk"
