Comments on glib testing framework
- From: Tommi Komulainen <tommi komulainen nokia com>
- To: gtk-devel-list <gtk-devel-list gnome org>
- Subject: Comments on glib testing framework
- Date: Wed, 09 Jan 2008 12:12:57 +0200
Hi,
Me and Xan Lopez just tried out using the glib testing framework in a
separate module (in our case, hildon.) Following are notes from our
experiment.
Overall it's a fairly decent testing framework for API level testing.
However writing test cases for user interactions, especially on
composite black box widgets can be a bit cumbersome.
Documentation is missing (highlevel and API reference.) There was no
guide for how to set up your own project to use the glib testing
framework (I'll send a quick guide separately) or higher level overview
of setup/teardown, available asserts, gtk helpers, running, parameters,
etc. Given the testing framework is still young this is understandable.
For custom objects/widgets it would be nice to be able to have some
generic tests for things such as:
* default object properties; create an object, verify all
properties have default values
* interfaces; for all interfaces provided by an object, if
possible verify the API contract holds
* gtk_editable_set_editable(FALSE) + cut() shouldn't
delete text
* gtk_container_add(parent, child) => g_assert
(child->parent == parent)
* ...
make -k test probably shouldn't abort gtester on first failing assertion
glib/gtestutils.h references g_object_unref() which requires gobject.
It would be nice to have g_assert_cmpenum and g_assert_cmpflags to
pretty print the name of enum/flags rather than plain numerical value
(See example code for cmpenum attached, needs to be in gobject.) For
example:
assertion failed (mode == GTK_SIZE_GROUP_HORIZONTAL): (3 (GTK_SIZE_GROUP_BOTH) == 1 (GTK_SIZE_GROUP_HORIZONTAL))
While we are on this topic, does it make sense to add something like
g_enum_get_name (GType, gint)? The g_enum_* functions can be used to do
this, but are a bit cumbersome to use.
gtk_test_create_widget is nice, but unfortunately won't be usable in the
cases where a widget does more than a g_object_new call in its _new
function (GtkSpinButton, text variants of comboboxes, GtkAspectFrame,
any other third party widget, ...). Maybe not too important, but worth
noting.
gtk_test_teardown. See bug #507256
There are two technologies that could help in the creation of testcases:
* A way to record a series of events and replay them at will.
(Already exists?)
* A way to record either the static aspect (screenshot) or an
extended period of time (video, or series of images matched with
a checkpoint) and compare it against a pre-defined image/video.
Combining both features some pretty complex tests could be defined very
easily; for example: Build a menu, populate it, replay a series of
events and check that the menu aspect matches the data previously
defined. A simple UI could be developed to create this kind of graphical
unit testing.
The downside of this approach is that it would be theme/font size/etc
specific.
--
Tommi Komulainen <tommi komulainen nokia com>
#include <gtk/gtk.h>
#define g_assert_cmpenum(n1,cmp,n2,t) do { gint64 __n1 = (n1), __n2 = (n2); \
if (__n1 cmp __n2) ; else \
g_assertion_message_cmpenum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
#n1 " " #cmp " " #n2, (t), __n1, #cmp, __n2); } while (0)
void
g_assertion_message_cmpenum (const char *domain,
const char *file,
int line,
const char *func,
const char *expr,
GType enum_type,
gint arg1,
const char *cmp,
gint arg2)
{
GEnumClass *enum_class;
GEnumValue *val1, *val2;
char *a1, *a2, *s;
enum_class = g_type_class_ref (enum_type);
g_assert (G_IS_ENUM_CLASS (enum_class));
val1 = g_enum_get_value (enum_class, arg1);
val2 = g_enum_get_value (enum_class, arg2);
a1 = val1 ? g_strdup_printf ("%d (%s)", arg1, val1->value_name) : g_strdup_printf ("%d", arg1);
a2 = val2 ? g_strdup_printf ("%d (%s)", arg2, val2->value_name) : g_strdup_printf ("%d", arg2);
s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
g_free (a1);
g_free (a2);
g_assertion_message (domain, file, line, func, s);
g_free (s);
g_type_class_unref (enum_class);
}
int
main (int argc, char **argv)
{
gint mode;
g_type_init ();
mode = GTK_SIZE_GROUP_HORIZONTAL;
g_assert_cmpenum (mode, ==, GTK_SIZE_GROUP_BOTH, GTK_TYPE_SIZE_GROUP_MODE);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]