diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 28b80229646c..6fe09b743221 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -72,6 +72,7 @@ typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
 
 enum GDBusFlags {
 	G_DBUS_FLAG_ENABLE_EXPERIMENTAL = (1 << 0),
+	G_DBUS_FLAG_ENABLE_TESTING      = (1 << 1),
 };
 
 enum GDBusMethodFlags {
@@ -79,16 +80,19 @@ enum GDBusMethodFlags {
 	G_DBUS_METHOD_FLAG_NOREPLY      = (1 << 1),
 	G_DBUS_METHOD_FLAG_ASYNC        = (1 << 2),
 	G_DBUS_METHOD_FLAG_EXPERIMENTAL = (1 << 3),
+	G_DBUS_METHOD_FLAG_TESTING      = (1 << 4),
 };
 
 enum GDBusSignalFlags {
 	G_DBUS_SIGNAL_FLAG_DEPRECATED   = (1 << 0),
 	G_DBUS_SIGNAL_FLAG_EXPERIMENTAL = (1 << 1),
+	G_DBUS_SIGNAL_FLAG_TESTING      = (1 << 2),
 };
 
 enum GDBusPropertyFlags {
 	G_DBUS_PROPERTY_FLAG_DEPRECATED   = (1 << 0),
 	G_DBUS_PROPERTY_FLAG_EXPERIMENTAL = (1 << 1),
+	G_DBUS_PROPERTY_FLAG_TESTING      = (1 << 2),
 };
 
 enum GDBusSecurityFlags {
@@ -186,6 +190,20 @@ struct GDBusSecurityTable {
 	.function = _function, \
 	.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_EXPERIMENTAL
 
+#define GDBUS_TESTING_METHOD(_name, _in_args, _out_args, _function) \
+	.name = _name, \
+	.in_args = _in_args, \
+	.out_args = _out_args, \
+	.function = _function, \
+	.flags = G_DBUS_METHOD_FLAG_TESTING
+
+#define GDBUS_TESTING_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+	.name = _name, \
+	.in_args = _in_args, \
+	.out_args = _out_args, \
+	.function = _function, \
+	.flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_TESTING
+
 #define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \
 	.name = _name, \
 	.in_args = _in_args, \
@@ -207,6 +225,11 @@ struct GDBusSecurityTable {
 	.args = _args, \
 	.flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL
 
+#define GDBUS_TESTING_SIGNAL(_name, _args) \
+	.name = _name, \
+	.args = _args, \
+	.flags = G_DBUS_SIGNAL_FLAG_EXPERIMENTAL
+
 void g_dbus_set_flags(int flags);
 int g_dbus_get_flags(void);
 
diff --git a/gdbus/object.c b/gdbus/object.c
index f7c8c2be5d87..72d2d46e30ef 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -115,6 +116,14 @@ static gboolean check_experimental(int flags, int flag)
 	return !(global_flags & G_DBUS_FLAG_ENABLE_EXPERIMENTAL);
 }
 
+static bool check_testing(int flags, int flag)
+{
+	if (!(flags & flag))
+		return false;
+
+	return !(global_flags & G_DBUS_FLAG_ENABLE_TESTING);
+}
+
 static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 {
 	const GDBusMethodTable *method;
@@ -126,6 +135,9 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<method name=\"%s\">",
 								method->name);
 		print_arguments(gstr, method->in_args, "in");
@@ -146,6 +158,9 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(signal->flags, G_DBUS_SIGNAL_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<signal name=\"%s\">",
 								signal->name);
 		print_arguments(gstr, signal->args, NULL);
@@ -163,6 +178,10 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(property->flags,
+					G_DBUS_PROPERTY_FLAG_TESTING))
+			continue;
+
 		g_string_append_printf(gstr, "<property name=\"%s\""
 					" type=\"%s\" access=\"%s%s\">",
 					property->name,	property->type,
@@ -518,6 +537,9 @@ static void append_properties(struct interface_data *data,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			continue;
 
+		if (check_testing(p->flags, G_DBUS_PROPERTY_FLAG_TESTING))
+			continue;
+
 		if (p->get == NULL)
 			continue;
 
@@ -749,6 +771,9 @@ static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			break;
 
+		if (check_testing(p->flags, G_DBUS_PROPERTY_FLAG_TESTING))
+			break;
+
 		return p;
 	}
 
@@ -1061,6 +1086,9 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
+		if (check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
 		if (g_dbus_args_have_signature(method->in_args,
 							message) == FALSE)
 			continue;
@@ -1190,18 +1218,26 @@ static gboolean add_interface(struct generic_data *data,
 		if (!check_experimental(method->flags,
 					G_DBUS_METHOD_FLAG_EXPERIMENTAL))
 			goto done;
+
+		if (!check_testing(method->flags, G_DBUS_METHOD_FLAG_TESTING))
+			goto done;
 	}
 
 	for (signal = signals; signal && signal->name; signal++) {
 		if (!check_experimental(signal->flags,
 					G_DBUS_SIGNAL_FLAG_EXPERIMENTAL))
 			goto done;
+		if (!check_testing(signal->flags, G_DBUS_SIGNAL_FLAG_TESTING))
+			goto done;
 	}
 
 	for (property = properties; property && property->name; property++) {
 		if (!check_experimental(property->flags,
 					G_DBUS_PROPERTY_FLAG_EXPERIMENTAL))
 			goto done;
+		if (!check_testing(property->flags,
+					G_DBUS_PROPERTY_FLAG_TESTING))
+			goto done;
 	}
 
 	/* Nothing to register */
