Qt Test Buenas prácticas
Te recomendamos que añadas Qt Test para corregir errores y nuevas características. Antes de intentar corregir un error, añade una prueba de regresión (idealmente automática) que falle antes de la corrección, mostrando el error, y pase después de la corrección. Mientras desarrollas nuevas funciones, añade pruebas para verificar que funcionan según lo previsto.
Ajustarse a un conjunto de normas de codificación hará más probable que las pruebas automáticas de Qt funcionen de forma fiable en todos los entornos. Por ejemplo, algunas pruebas necesitan leer datos del disco. Si no se establecen normas sobre cómo hacerlo, algunas pruebas no serán portables. Por ejemplo, una prueba que asume que sus archivos de datos de prueba están en el directorio de trabajo actual sólo funciona para una compilación dentro del código fuente. En una compilación sombra (fuera del directorio fuente), la prueba no encontrará sus datos.
Las siguientes secciones contienen directrices para escribir tests Qt:
- Principios generales
- Escribir tests fiables
- Mejora de los resultados de las pruebas
- Escribir código comprobable
- Configuración de máquinas de pruebas
Principios generales
Las siguientes secciones proporcionan directrices generales para escribir pruebas unitarias:
- Verificación de pruebas
- Dar nombres descriptivos a las funciones de prueba
- Escribir funciones de prueba autónomas
- Pruebe toda la pila
- Haga que las pruebas se completen rápidamente
- Utilizar pruebas basadas en datos
- Utilizar Herramientas de Cobertura
- Seleccionar mecanismos apropiados para excluir pruebas
- Evitar Q_ASSERT
Verifique las pruebas
Escribe y confirma tus pruebas junto con tu corrección o nueva característica en una nueva rama. Una vez que hayas terminado, puedes comprobar la rama en la que se basa tu trabajo, y luego comprobar en esta rama los archivos de prueba para tus nuevas pruebas. Esto te permite verificar que las pruebas fallan en la rama anterior y, por tanto, detectan un error o prueban una nueva funcionalidad.
Por ejemplo, el flujo de trabajo para corregir un error en la clase QDateTime podría ser el siguiente si utilizas el sistema de control de versiones Git:
- Crea una rama para tu corrección y prueba:
git checkout -b fix-branch 5.14 - Escribe una prueba y corrige el error.
- Construye y prueba tanto la corrección como el nuevo test, para verificar que el nuevo test pasa con la corrección.
- Añade la corrección y la prueba a tu rama:
git add tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp src/corelib/time/qdatetime.cpp - Confirma la corrección y la prueba en tu rama:
git commit -m 'Fix bug in QDateTime' - Para verificar que la prueba realmente detecta algo para lo que necesitabas la corrección, comprueba la rama en la que has basado tu propia rama:
git checkout 5.14 - Comprueba sólo el archivo de prueba en la rama 5.14:
git checkout fix-branch -- tests/auto/corelib/time/qdatetime/tst_qdatetime.cppSólo la prueba está ahora en la rama de corrección. El resto del árbol de fuentes sigue en la 5.14.
- Construye y ejecuta la prueba para verificar que falla en 5.14, y por lo tanto detecta un error.
- Ahora puede volver a la rama fija:
git checkout fix-branch - Alternativamente, puede restaurar su árbol de trabajo a un estado limpio en 5.14:
git checkout HEAD -- tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
Cuando esté revisando un cambio, puede adaptar este flujo de trabajo para comprobar que el cambio efectivamente viene con una prueba para un problema que corrige.
Dar nombres descriptivos a las funciones de prueba
Nombrar los casos de prueba es importante. El nombre de la prueba aparece en el informe de fallos de una ejecución de prueba. Para las pruebas basadas en datos, el nombre de la fila de datos también aparece en el informe de fallos. Los nombres dan a quienes leen el informe una primera indicación de lo que ha ido mal.
Los nombres de las funciones de prueba deben dejar claro qué es lo que la función intenta probar. No utilice simplemente el identificador de seguimiento de fallos, porque los identificadores quedan obsoletos si se sustituye el seguidor de fallos. Además, algunos gestores de fallos pueden no ser accesibles a todos los usuarios. Cuando el informe del fallo pueda ser de interés para posteriores lectores del código de la prueba, puedes mencionarlo en un comentario junto a una parte relevante de la prueba.
Del mismo modo, cuando escribas pruebas basadas en datos, da nombres descriptivos a los casos de prueba, que indiquen en qué aspecto de la funcionalidad se centra cada uno. No te limites a numerar los casos de prueba ni utilices identificadores de seguimiento de errores. Alguien que lea el resultado de la prueba no tendrá ni idea de lo que significan los números o identificadores. Puedes añadir un comentario en la fila de prueba que mencione el identificador de seguimiento de fallos, cuando sea relevante. Es mejor evitar los caracteres de espaciado y los caracteres que puedan ser significativos para los intérpretes de comandos en los que quiera ejecutar las pruebas. Esto facilita la especificación de la prueba y la etiqueta en la línea de comandos de su programa de pruebas, por ejemplo, para limitar la ejecución de una prueba a un solo caso de prueba.
Escriba funciones de prueba autónomas
Dentro de un programa de pruebas, las funciones de prueba deben ser independientes entre sí y no depender de la ejecución de funciones de prueba anteriores. Puede comprobarlo ejecutando la función de prueba por sí sola con tst_foo testname.
No reutilice instancias de la clase sometida a prueba en varias pruebas. Las instancias de prueba (por ejemplo, los widgets) no deben ser variables miembro de las pruebas, sino que es preferible instanciarlas en la pila para garantizar una limpieza adecuada incluso si falla una prueba, de modo que las pruebas no interfieran entre sí.
Si su prueba implica realizar cambios globales, asegúrese de que el estado anterior se restaura al final de la prueba, tanto si pasa como si falla. Dado que el fallo impide que se ejecute código posterior a la comprobación que falla, la restauración al final de la prueba no funciona cuando la prueba falla. La forma robusta de restaurar incluso en caso de fallo es instanciar un objeto RAII cuyo destructor restaure el estado anterior. Esto puede hacerse convenientemente usando qScopeGuard, por ejemplo
const auto restoreDefaultLocale = qScopeGuard([prior = QLocale()]() { QLocale::setDefault(prior); });
antes de la primera llamada a QLocale::setDefault() en una prueba que necesita controlar la configuración regional utilizada por el código bajo prueba.
Probar toda la pila
Si una API se implementa en términos de backends enchufables o específicos de la plataforma que hacen el trabajo pesado, asegúrate de escribir pruebas que cubran las rutas de código hasta los backends. Probar las partes de la capa superior de la API utilizando un backend simulado es una buena forma de aislar los errores en la capa de la API de los backends, pero es complementario a las pruebas que ejecutan la implementación real con datos del mundo real.
Haz que las pruebas se completen rápidamente
Las pruebas no deben perder el tiempo siendo innecesariamente repetitivas, utilizando volúmenes de datos de prueba inadecuadamente grandes o introduciendo tiempos muertos innecesarios.
Esto es particularmente cierto para las pruebas unitarias, donde cada segundo extra de tiempo de ejecución de pruebas unitarias hace que las pruebas CI de una rama a través de múltiples objetivos tomen más tiempo. Recuerde que las pruebas unitarias son independientes de las pruebas de carga y fiabilidad, en las que se esperan mayores volúmenes de datos de prueba y ejecuciones de prueba más largas.
Las pruebas de referencia, que normalmente ejecutan la misma prueba varias veces, deben ubicarse en un directorio tests/benchmarks separado y no deben mezclarse con las pruebas unitarias funcionales.
Pruebas basadas en datos
Las pruebasbasadas en datos facilitan la adición de nuevas pruebas para condiciones límite detectadas en informes de errores posteriores.
Utilizar una prueba basada en datos en lugar de probar varios elementos en secuencia en una prueba ahorra la repetición de código muy similar y garantiza que los casos posteriores se prueben incluso cuando fallan los anteriores. También fomenta la realización de pruebas sistemáticas y uniformes, ya que se aplican las mismas pruebas a cada muestra de datos.
Cuando una prueba se basa en datos, puede especificar su etiqueta de datos junto con el nombre de la función de prueba, como function:tag, en la línea de comandos de la prueba para ejecutar la prueba sólo en un caso de prueba específico, en lugar de en todos los casos de prueba de la función. Esto puede utilizarse tanto para una etiqueta de datos global como para una etiqueta local, que identifica una fila de los propios datos de la función; incluso puede combinarlas como function:global:local.
Utilice herramientas de cobertura
Utilice una herramienta de cobertura como Coco o gcov para ayudar a escribir pruebas que cubran tantas declaraciones, ramas y condiciones como sea posible en la función o clase que se está probando. Cuanto antes se haga esto en el ciclo de desarrollo de una nueva función, más fácil será detectar regresiones más adelante, cuando se refactorice el código.
Seleccionar mecanismos apropiados para excluir pruebas
Es importante seleccionar el mecanismo adecuado para excluir las pruebas no aplicables.
Utilice QSKIP() para tratar los casos en los que una función de prueba completa resulta inaplicable en el entorno de prueba actual. Cuando sólo debe omitirse una parte de una función de prueba, puede utilizarse una sentencia condicional, opcionalmente con una llamada a qDebug() para informar del motivo por el que se omite la parte no aplicable.
Cuando hay fallos conocidos en la prueba que deben solucionarse eventualmente, se recomienda QEXPECT_FAIL, ya que permite ejecutar el resto de la prueba, cuando es posible. También verifica que el problema sigue existiendo, y avisa al mantenedor del código en caso de que lo solucione involuntariamente, una ventaja que se obtiene incluso cuando se utiliza la bandera Abort.
Las funciones de prueba o las filas de datos de una prueba basada en datos pueden limitarse a plataformas concretas, o a características concretas habilitadas mediante #if. Sin embargo, hay que tener cuidado con las limitaciones de moc cuando se utiliza #if para omitir funciones de prueba. El preprocesador moc no tiene acceso a todas las macros builtin del compilador que suelen utilizarse para la detección de características del compilador. Por lo tanto, moc podría obtener un resultado diferente para una condición del preprocesador que el visto por el resto de tu código. Esto puede dar lugar a que moc genere metadatos para una ranura de prueba que el compilador real se salta, u omita los metadatos para una ranura de prueba que realmente se compila en la clase. En el primer caso, la prueba intentará ejecutar una ranura que no está implementada. En el segundo caso, la prueba no intentará ejecutar una ranura de prueba aunque debería hacerlo.
Si un programa de prueba completo es inaplicable para una plataforma específica o a menos que se active una función concreta, lo mejor es utilizar la configuración de compilación del directorio principal para evitar la compilación de la prueba. Por ejemplo, si la prueba tests/auto/gui/someclass no es válida para macOS, incluya su inclusión como subdirectorio en tests/auto/gui/CMakeLists.txt en una comprobación de plataforma:
if(NOT APPLE)
add_subdirectory(someclass)
endifo, si utiliza qmake, añada la siguiente línea a tests/auto/gui.pro:
mac*: SUBDIRS -= someclass
Véase también Omitir pruebas con QSKIP.
Evitar Q_ASSERT
La macro Q_ASSERT hace que un programa aborte siempre que la condición afirmada sea false, pero sólo si el software fue construido en modo depuración. Tanto en release como en debug-and-release, Q_ASSERT no hace nada.
Q_ASSERT debería evitarse porque hace que las pruebas se comporten de forma diferente dependiendo de si se está probando una compilación de depuración, y porque hace que una prueba aborte inmediatamente, saltándose todas las funciones de prueba restantes y devolviendo resultados de prueba incompletos o malformados.
También se salta cualquier desmontaje u ordenación que se suponía que iba a ocurrir al final de la prueba, y por lo tanto podría dejar el espacio de trabajo en un estado desordenado, lo que podría causar complicaciones para las pruebas posteriores.
En lugar de Q_ASSERT, deberían utilizarse las variantes de macro QCOMPARE() o QVERIFY(). Éstas hacen que la prueba actual informe de un fallo y finalice, pero permiten que se ejecuten las funciones de prueba restantes y que todo el programa de prueba finalice normalmente. QVERIFY2() permite incluso registrar un mensaje de error descriptivo en el registro de la prueba.
Cómo escribir pruebas fiables
En las secciones siguientes se ofrecen directrices para escribir pruebas fiables:
- Evitar efectos secundarios en los pasos de verificación
- Evite los tiempos de espera fijos
- Cuidado con el comportamiento dependiente del tiempo
- Evitar la captura y comparación de mapas de bits
Evitar efectos secundarios en los pasos de verificación
Cuando se realizan pasos de verificación en un autotest utilizando QCOMPARE(), QVERIFY(), etc., deben evitarse los efectos secundarios. Los efectos secundarios en los pasos de verificación pueden dificultar la comprensión de una prueba. Además, pueden romper fácilmente una prueba de maneras que son difíciles de diagnosticar cuando la prueba se cambia para utilizar QTRY_VERIFY(), QTRY_COMPARE() o QBENCHMARK(). Estos pueden ejecutar la expresión pasada varias veces, repitiendo así cualquier efecto secundario.
Cuando los efectos secundarios son inevitables, asegúrese de que el estado anterior se restaura al final de la función de prueba, incluso si la prueba falla. Esto suele requerir el uso de una clase RAII (adquisición de recursos es inicialización) que restaura el estado cuando vuelve la función, o un método cleanup(). No coloque simplemente el código de restauración al final de la prueba. Si parte de la prueba falla, dicho código se saltará y no se restaurará el estado anterior.
Evite los tiempos de espera fijos
Evite utilizar tiempos de espera fijos, como QTest::qWait() para esperar a que se cumplan algunas condiciones. Considere el uso de la clase QSignalSpy, las macros QTRY_VERIFY() o QTRY_COMPARE(), o la clase QSignalSpy junto con las variantes de la macro QTRY_.
La función qWait() puede utilizarse para establecer un retardo durante un periodo fijo entre la realización de alguna acción y la espera a que se complete algún comportamiento asíncrono desencadenado por dicha acción. Por ejemplo, cambiar el estado de un widget y esperar a que se vuelva a pintar. Sin embargo, estos tiempos de espera a menudo provocan fallos cuando una prueba escrita en una estación de trabajo se ejecuta en un dispositivo, donde el comportamiento esperado puede tardar más en completarse. Aumentar el tiempo de espera fijo a un valor varias veces superior al necesario en la plataforma de prueba más lenta no es una buena solución, porque ralentiza la ejecución de la prueba en todas las plataformas, en particular para las pruebas basadas en tablas.
Si el código bajo prueba emite señales Qt en la finalización del comportamiento asíncrono, un mejor enfoque es utilizar la clase QSignalSpy para notificar a la función de prueba que el paso de verificación se puede realizar ahora.
Si no hay señales Qt, utilice las macros QTRY_COMPARE() y QTRY_VERIFY(), que comprueban periódicamente una condición especificada hasta que se convierte en verdadera o se alcanza un tiempo máximo de espera. Estas macros evitan que la prueba se prolongue más de lo necesario, a la vez que evitan interrupciones cuando las pruebas se escriben en estaciones de trabajo y se ejecutan posteriormente en plataformas integradas.
Si no hay señales Qt, y está escribiendo la prueba como parte del desarrollo de una nueva API, considere si la API podría beneficiarse de la adición de una señal que informe de la finalización del comportamiento asíncrono.
Cuidado con el comportamiento dependiente del tiempo
Algunas estrategias de prueba son vulnerables al comportamiento dependiente del tiempo de determinadas clases, lo que puede dar lugar a pruebas que fallen sólo en determinadas plataformas o que no devuelvan resultados coherentes.
Un ejemplo de esto son los widgets de entrada de texto, que a menudo tienen un cursor parpadeante que puede hacer que las comparaciones de mapas de bits capturados tengan éxito o fallen dependiendo del estado del cursor cuando se captura el mapa de bits. Esto, a su vez, puede depender de la velocidad de la máquina que ejecuta la prueba.
Cuando se prueban clases que cambian su estado basándose en eventos de temporizador, es necesario tener en cuenta el comportamiento basado en temporizador al realizar los pasos de verificación. Debido a la variedad del comportamiento dependiente del temporizador, no existe una única solución genérica a este problema de comprobación.
Para los widgets de entrada de texto, las posibles soluciones incluyen desactivar el comportamiento de parpadeo del cursor (si la API proporciona esa función), esperar a que el cursor esté en un estado conocido antes de capturar un mapa de bits (por ejemplo, suscribiéndose a una señal adecuada si la API proporciona una) o excluir el área que contiene el cursor de la comparación del mapa de bits.
Evitar la captura y comparación de mapas de bits
Aunque a veces es necesario verificar los resultados de las pruebas capturando y comparando mapas de bits, puede resultar bastante frágil y laborioso.
Por ejemplo, un widget concreto puede tener un aspecto diferente en distintas plataformas o con distintos estilos de widget, por lo que puede ser necesario crear mapas de bits de referencia varias veces y mantenerlos en el futuro a medida que evolucione el conjunto de plataformas compatibles con Qt. Hacer cambios que afecten al mapa de bits significa, por tanto, tener que recrear los mapas de bits esperados en cada plataforma soportada, lo que requeriría acceso a cada plataforma.
Las comparaciones de mapas de bits también pueden verse influidas por factores como la resolución de pantalla de la máquina de pruebas, la profundidad de bits, el tema activo, la combinación de colores, el estilo del widget, la configuración regional activa (símbolos monetarios, dirección del texto, etc.), el tamaño de la fuente, los efectos de transparencia y la elección del gestor de ventanas.
Siempre que sea posible, utilice medios programáticos, como la comprobación de propiedades de objetos y variables, en lugar de capturar y comparar mapas de bits.
Mejora de los resultados de las pruebas
En las secciones siguientes se ofrecen directrices para producir resultados de prueba legibles y útiles:
- Comprobación de advertencias
- Evite imprimir mensajes de depuración desde las pruebas automáticas
- Escribir código de diagnóstico bien estructurado
Comprobación de advertencias
Al igual que ocurre al crear el software, si los resultados de las pruebas están repletos de advertencias, le resultará más difícil detectar una advertencia que realmente sea una pista de la aparición de un error. Por lo tanto, es prudente comprobar periódicamente los registros de las pruebas en busca de advertencias y otros resultados extraños, e investigar las causas. Cuando sean indicios de un fallo, puede hacer que las advertencias provoquen el fallo de la prueba.
Cuando el código sometido a prueba deba producir mensajes, como advertencias sobre un uso incorrecto, también es importante comprobar que los produce cuando se utiliza. Puedes probar los mensajes esperados del código bajo prueba, producidos por qWarning(), qDebug(), qInfo() y amigos, utilizando QTest::ignoreMessage(). Esto verificará que se produce el mensaje y lo filtrará de la salida de la ejecución de la prueba. Si el mensaje no se produce, la prueba fallará.
Si un mensaje esperado sólo se produce cuando Qt se construye en modo de depuración, utilice QLibraryInfo::isDebugBuild() para determinar si las bibliotecas Qt se construyeron en modo de depuración. El uso de #ifdef QT_DEBUG no es suficiente, ya que sólo le dirá si la prueba se construyó en modo de depuración, y eso no garantiza que las bibliotecas Qt también se construyeron en modo de depuración.
Tus tests pueden (desde Qt 6.3) verificar que no activan llamadas a qWarning() llamando a QTest::failOnWarning(). Esto toma el mensaje de advertencia a comprobar o un QRegularExpression para compararlo con las advertencias; si se produce una advertencia coincidente, se informará de ella y hará que la prueba falle. Por ejemplo, una prueba que no debería producir ninguna advertencia puede QTest::failOnWarning(QRegularExpression(u".*"_s)), que coincidirá con cualquier advertencia.
También puede establecer la variable de entorno QT_FATAL_WARNINGS para que las advertencias se traten como errores fatales. Consulte qWarning() para más detalles; esto no es específico de los autotests. Si las advertencias se pierden en los registros de pruebas, la ejecución ocasional con esta variable de entorno puede ayudarle a encontrar y eliminar las que se produzcan.
Evite imprimir mensajes de depuración desde los autotests
Las autopruebas no deberían producir mensajes de advertencia o depuración no gestionados. Esto permitirá a CI Gate tratar nuevos mensajes de advertencia o depuración como fallos de prueba.
Añadir mensajes de depuración durante el desarrollo está bien, pero deben desactivarse o eliminarse antes de comprobar una prueba.
Escribir código de diagnóstico bien estructurado
Cualquier salida de diagnóstico que pueda ser útil en caso de fallo de una prueba debe formar parte de la salida normal de la prueba en lugar de estar comentada, desactivada mediante directivas del preprocesador o activada sólo en las compilaciones de depuración. Si una prueba falla durante la integración continua, tener toda la salida de diagnóstico relevante en los registros de CI podría ahorrarle mucho tiempo en comparación con habilitar el código de diagnóstico y volver a probar. Especialmente, si el fallo fue en una plataforma que no tienes en tu escritorio.
Los mensajes de diagnóstico en los tests deberían usar los mecanismos de salida de Qt, como qDebug() y qWarning(), en lugar de los mecanismos de salida stdio.h o iostream.h. Estos últimos eluden el manejo de mensajes de Qt y evitan que la opción de línea de comandos -silent suprima los mensajes de diagnóstico. Esto podría provocar que importantes mensajes de error quedaran ocultos en un gran volumen de salida de depuración.
Escribir código comprobable
Las siguientes secciones proporcionan directrices para escribir código que sea fácil de probar:
Romper dependencias
La idea de las pruebas unitarias es utilizar cada clase de forma aislada. Dado que muchas clases instancian otras clases, no es posible instanciar una clase por separado. Por lo tanto, debe utilizar una técnica llamada inyección de dependencia que separa la creación de objetos del uso de objetos. Una fábrica se encarga de construir árboles de objetos. Otros objetos manipulan estos objetos a través de interfaces abstractas.
Esta técnica funciona bien para aplicaciones basadas en datos. Para aplicaciones GUI, este enfoque puede ser difícil ya que los objetos se crean y destruyen con frecuencia. Para verificar el comportamiento correcto de las clases que dependen de interfaces abstractas, se puede utilizar mocking. Por ejemplo, véase Googletest Mocking (gMock) Framework.
Compilar todas las clases en bibliotecas
En proyectos pequeños y medianos, un script de compilación normalmente lista todos los archivos fuente y luego compila el ejecutable de una sola vez. Esto significa que los scripts de compilación para las pruebas deben listar de nuevo los archivos fuente necesarios.
Es más fácil listar los archivos fuente y las cabeceras sólo una vez en un script para construir una biblioteca estática. A continuación, la función main() se enlazará con la biblioteca estática para construir el ejecutable y las pruebas se enlazarán con las bibliotecas estáticas.
Para proyectos en los que se utilizan los mismos archivos fuente en la construcción de varios programas, puede ser más apropiado construir las clases compartidas en una biblioteca enlazada dinámicamente (o de objetos compartidos) que cada programa, incluyendo los programas de prueba, pueda cargar en tiempo de ejecución. De nuevo, tener el código compilado en una biblioteca ayuda a evitar la duplicación en la descripción de qué componentes combinar para crear los distintos programas.
Configuración de máquinas de prueba
En las siguientes secciones se analizan los problemas comunes causados por la configuración de las máquinas de prueba:
Todos estos problemas pueden solucionarse con un uso adecuado de la virtualización.
Salvapantallas
Los protectores de pantalla pueden interferir con algunas de las pruebas de las clases GUI, provocando resultados poco fiables. Los salvapantallas deben desactivarse para garantizar que los resultados de las pruebas sean coherentes y fiables.
Diálogos del sistema
Los diálogos mostrados inesperadamente por el sistema operativo u otras aplicaciones en ejecución pueden robar el foco de entrada de los widgets implicados en una prueba automática, provocando fallos irreproducibles.
Algunos ejemplos de problemas típicos son los cuadros de diálogo de notificación de actualizaciones en línea en macOS, las falsas alarmas de los escáneres de virus, las tareas programadas como las actualizaciones de firmas de virus, las actualizaciones de software enviadas a las estaciones de trabajo y los programas de chat que abren ventanas en la parte superior de la pila.
Uso de la pantalla
Algunas pruebas utilizan la pantalla, el ratón y el teclado de la máquina de pruebas, por lo que pueden fallar si la máquina se utiliza para otra cosa al mismo tiempo o si se ejecutan varias pruebas en paralelo.
El sistema CI utiliza máquinas de prueba dedicadas para evitar este problema, pero si usted no tiene una máquina de prueba dedicada, puede ser capaz de resolver este problema mediante la ejecución de las pruebas en una segunda pantalla.
En Unix, también se pueden ejecutar las pruebas en un servidor X anidado o virtual, como Xephyr. Por ejemplo, para ejecutar todo el conjunto de pruebas en Xephyr, ejecute los siguientes comandos:
Xephyr :1 -ac -screen 1920x1200 >/dev/null 2>&1 & sleep 5 DISPLAY=:1 icewm >/dev/null 2>&1 & cd tests/auto make DISPLAY=:1 make -k -j1 check
Los usuarios de controladores binarios NVIDIA deben tener en cuenta que Xephyr podría no ser capaz de proporcionar extensiones GLX. Forzar Mesa libGL podría ayudar:
export LD_PRELOAD=/usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1
Sin embargo, cuando las pruebas se ejecutan en Xephyr y en el servidor X real con diferentes versiones de libGL, la caché de disco QML puede hacer que las pruebas se bloqueen. Para evitarlo, utiliza QML_DISABLE_DISK_CACHE=1.
Alternativamente, usa el plugin offscreen:
TESTARGS="-platform offscreen" make check -k -j1
Gestores de ventanas
En Unix, al menos dos pruebas automáticas (tst_examples y tst_gestures) requieren la ejecución de un gestor de ventanas. Por lo tanto, si ejecuta estas pruebas bajo un servidor X anidado, también debe ejecutar un gestor de ventanas en ese servidor X.
Su gestor de ventanas debe estar configurado para posicionar todas las ventanas en la pantalla automáticamente. Algunos gestores de ventanas, como Tab Window Manager (twm), tienen un modo para posicionar manualmente las nuevas ventanas, y esto impide que el conjunto de pruebas se ejecute sin la interacción del usuario.
Nota: Tab Window Manager no es adecuado para ejecutar el conjunto completo de pruebas automáticas de Qt, ya que la prueba automática tst_gestures hace que olvide su configuración y vuelva a la colocación manual de ventanas.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.