c++ - electrónico - Usando google simulacro para el código C
libro electronico (3)
A partir de las preguntas frecuentes de Google Mock:
Mi código llama a una función estática / global. ¿Me puedo burlar?
Puedes, pero necesitas hacer algunos cambios.En general, si necesita simular una función estática, es una señal de que sus módulos están demasiado apretados (y son menos flexibles, menos reutilizables, menos comprobables, etc.). Probablemente sea mejor definir una pequeña interfaz y llamar a la función a través de esa interfaz, que luego se puede burlar fácilmente. Inicialmente es un poco de trabajo, pero generalmente se amortiza rápidamente.
Esta post Google Testing Blog lo dice de manera excelente. Echale un vistazo.
Mantengo un proyecto heredado escrito en C y no es factible que se ejecute con un compilador de C ++. Dado que el código se compila de forma cruzada, sin embargo, es posible ejecutar pruebas unitarias o similares en un entorno host. por lo tanto, también es posible interactuar con un compilador de host C ++ y usar google-test y google-mock.
Hay ciertas capacidades de google-mock que parecen ser muy tentadoras de usar para probar como invocar implementaciones reales y establecer expectativas de llamada.
Me gustaría poder usarlos en el código C. Puedo ver que es posible usar google-mock sin usar vtables, pero requiere plantillas.
¿Hay una manera de burlar funciones C desnudas con Google Mock?
Encontré una manera de poder simular funciones C desnudas en google-mock.
La solución es declarar que foobar
es un alias débil que se asigna a foobarImpl
. En el código de producción, no implementa foobar()
y para las pruebas unitarias, proporciona una implementación que llama a un objeto simulado estático.
Esta solución es específica de GCC pero hay otros compiladores / enlazadores que proporcionan un aliasing débil.
- renombra la función
void foobar();
void foobarImpl();
- agregue un atributo a la función
foobar
como:void foobar() __attribute__((weak, alias("foobarImpl") ));
- Si desea tener un alias no débil, use una directiva del preprocesador para eliminar el débil de los atributos.
Por lo tanto:
#pragma once
void foobar();
se convierte en
// header.h
#pragma once
void foobar();
void foobarImpl(); // real implementation
y
extern "C" {
#include "header.h"
}
// code.c
void foobarImpl() {
/* do sth */
}
void foobar() __attribute__(( weak, alias ("foobarImpl") )); // declare foobar to be a weak alias of foobarImpl
Esto le indicará al enlazador gnu que vincule las llamadas de foobar()
con foobarImpl()
siempre que no haya un símbolo llamado foobar()
a continuación, agregue el código de prueba
struct FooInterface {
virtual ~FooInterface() {}
virtual void invokeFoo() const { }
};
class MockFoo : public FooInterface {
public:
MOCK_CONST_METHOD0(invokeFoo, void());
}
struct RealFoo : public FooInterface {
virtual ~RealFoo() {}
virtual void invokeFoo() const { foobarImpl(); }
};
MockFoo mockFoo;
RealFoo realFoo;
void foobar() {
mockFoo.invokeFoo();
}
Si este código está compilado y vinculado, reemplazará a foobar
con la llamada simulada. Si realmente quieres llamar a foobar()
, puedes agregar una invocación predeterminada.
ON_CALL(mockFoo, invokeFoo())
.WillByDefault(Invoke(&realFoo,&RealFoo::invokeFoo));
Su pregunta menciona específicamente Google Mock, pero luego no indica ninguna otra razón para usar ese marco. La otra respuesta sugiere usar una solución que parezca innecesariamente intrusiva.
Por lo tanto, espero que se me permita hacer una sugerencia alternativa que funcione bien sin tener que usar alias débiles, etc.
He usado CppUTest ( https://cpputest.github.io/ ) para la prueba de unidad con simulacros, con éxito en un par de proyectos grandes principalmente C (algunos C ++). La burla funciona sin tener que recurrir a ningún subterfugio del tipo anterior.
Desafortunadamente, la documentación del proyecto es un poco débil, algo mejor (aunque un poco ágil-doctrinaria) de información y ejemplos en el libro (también visto como un PDF) "Desarrollo guiado por pruebas para C embebido" - James W Greening (ISBN-13: 978-1-934356-62-3)