Pregunta

Me empezó a escribir algunas pruebas con el sistema de prueba de la unidad de Qt.

¿Cómo sueles organizar las pruebas? Es una clase de prueba por un módulo de clase, o se prueba todo el módulo con una sola clase de prueba? docs Qt sugieren seguir la estrategia anterior.

Quiero escribir pruebas para un módulo. El módulo proporciona sólo una clase que va a ser utilizado por el usuario módulo, pero hay una gran cantidad de lógica abstraído en otras clases, que también me gustaría a prueba, además de probar la clase pública.

El problema es que la forma propuesta de Qt para ejecutar las pruebas consistió en la macro QTEST_MAIN:

QTEST_MAIN(TestClass)
#include "test_class.moc"

y, finalmente, un programa de prueba es capaz de probar sólo una clase de prueba. Y es un poco aspira a crear proyectos de prueba para cada clase individual en el módulo.

Por supuesto, uno podría echar un vistazo a la macro QTEST_MAIN, volver a escribir, y ejecutar otras clases de prueba. Pero es que hay algo, que funciona fuera de la caja?

Hasta ahora lo hago con la mano:

#include "one.h"
#include "two.h"

int main(int argc, char *argv[]) 
{ 
    QCoreApplication app(argc, argv); 
    TestOne one;
    QTest::qExec(&one, argc, argv);
    TestOne two;
    QTest::qExec(&two, argc, argv);
}
¿Fue útil?

Solución

Sí, las fuerzas Qtest mordió estructura de la prueba extraño y es generalmente inferior a Google Prueba / Marco Mock. Por un proyecto que estoy obligado a utilizar QTest (requisito del cliente), y así es como lo uso:

  1. Compilo todas las pruebas en conjunto como un proyecto de plantilla subdirectorio
  2. Para hacer más fácil la creación de nuevas pruebas, que comparten una gran cantidad de configuración del proyecto mediante el uso de archivos common.pri incluyo en el archivo de cada prueba .pro
  3. Si es posible, porcentaje que el directorio de archivos objeto de acelerar la compilación
  4. les funcionan utilizando un awk + + comando especialmente por lotes.

La creación de estos cuatro puntos es muy fácil y hace uso de QTest casi agradable. ¿Tiene algunos problemas con la ejecución de varias pruebas que no se resuelven por la configuración descritos anteriormente?

PS:. La ejecución de pruebas de la manera que lo hace, es decir, llamando a múltiples QTest :: qExec causa problemas con el modificador de línea de comandos -o - obtendrá sólo los resultados de la última clase probado

Otros consejos

En relación con la respuesta Publicado por @cjhuitt

Este es un ejemplo que elimina la necesidad de llamar manualmente cada objeto de prueba

Trato de evitar cosas como esta:

MyTestClass1 t1;   t1.run();
MyTestClass2 t2;   t2.run();
//etc...

Mi solución es dejar que la prueba de objetos heredan de una clase base que se suma a una lista estática El programa principal ejecuta entonces todos los objetos de prueba en esa lista. De ese modo, ninguna de las necesidades de código estructura de soportes que desea cambiar. Las únicas cosas que cambian son las clases de prueba a sí mismos.

Aquí es cómo lo hago:

qtestsuite.h - clase base para la prueba de objetos

#ifndef QTESTSUITE_H
#define QTESTSUITE_H

#include <QObject>
#include <vector>

class QTestSuite : public QObject
{
    Q_OBJECT
public:
    static std::vector<QObject*> m_suites;

public:
    explicit QTestSuite();

};

#endif // QTESTSUITE_H

qtestsuite.cpp

#include "qtestsuite.h"
#include <iostream>

std::vector<QObject*> QTestSuite::m_suites;

QTestSuite::QTestSuite() : QObject()
{
    m_suites.push_back(this);
}

testall.cpp - ejecuta las pruebas

#include "qtestsuite.h"

#include <QtTest/QtTest>
#include <iostream>

int main(int, char**)
{
    int failedSuitesCount = 0;
    std::vector<QObject*>::iterator iSuite;
    for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); iSuite++)
    {
        int result = QTest::qExec(*iSuite);
        if (result != 0)
        {
            failedSuitesCount++;
        }
    }
    return failedSuitesCount;
}

mytestsuite1.cpp - un objeto de prueba ejemplo, crear más de estos

#include "qtestsuite.h"

#include <QtTest/QtTest>

class MyTestSuite1: public QTestSuite
{
     Q_OBJECT
private slots:
    void aTestFunction();
    void anotherTestFunction();
};

void MyTestSuite1::aTestFunction()
{
    QString str = "Hello";
    QVERIFY(str.toUpper() == "this will fail");
}

void MyTestSuite1::anotherTestFunction()
{
    QString str = "Goodbye";
    QVERIFY(str.toUpper() == "GOODBYE");
}

static MyTestSuite1 instance;  //This is where this particular test is instantiated, and thus added to the static list of test suites

#include "mytestsuite1.moc"

También, para crear el archivo .pro

qmake -project "CONFIG += qtestlib"

En nuestra configuración con QTest, que hizo algunas cosas para que sea más agradable.

  • Definir una subclase de QObject que se utiliza como una clase base para cualquier nueva clase-test unidad.
  • En el constructor de esa clase, que añadir la instancia de la prueba a una lista estática de pruebas, y en el destructor que quitarla.
  • A continuación, tiene una función estática que los bucles a través de las pruebas y se ejecuta utilizando QTest::qExec(). (Acumulamos los valores volvieron cada vez, y el retorno que desde nuestra función.)
  • main() llama a esta función, y devuelve el resultado como el éxito / fracaso.
  • Por último, en la unidad de compilación de la propia prueba específica, que por lo general incluyen una instancia estática de esa clase.

Este medio de instalación que utiliza la clase será una instancia antes main() se ejecuta, por lo que se añadirá a la lista de clases a prueba cuando principales carreras. El marco requiere que sólo tiene que heredar la clase correctamente, y crear instancias de una instancia estática si siempre desea que se ejecute.

También en ocasiones crear otras pruebas opcionales, que se agregan en base a parámetros de línea de comandos.

Por lo general organizar pruebas con un ejecutable de prueba por clase bajo prueba.

y, finalmente, un programa de prueba es capaz de probar una sola prueba clase.

Esto es una cosa buena. Se aísla sus pruebas entre sí, evitando cosas como un accidente en una prueba de bloquear todas las otras pruebas. El accidente podría ser causada por un componente común en varias clases que se está probando. El patrón de los fallos sería entonces alertar a al origen subyacente del problema. Básicamente, usted tiene una mejor información de diagnóstico de los fallos si sus pruebas son independientes entre sí.

Que sea fácil de configurar múltiples archivos ejecutables y ejecutar cada prueba por separado. Use un corredor de prueba para desovar fuera todos los procesos de prueba.

Actualización:

He cambiado mi mente en esto de alguna manera. Una vez que tenga un gran programa con un montón de pruebas, que une cientos de ejecutables de prueba se vuelve muy lento. Mi nueva preferencia es poner todas las pruebas para una biblioteca en un archivo ejecutable y elegir qué pruebas para invocar el uso de argumentos de línea de comandos pasados ??al ejecutable de prueba.

El hecho de que reduce el número de ejecutables de cientos a decenas, pero conserva las ventajas de la realización de pruebas por separado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top