2012-02-22 10 views
6

Estoy tratando de ejecutar una prueba de unidad GUI con DUnit a una aplicación cuya forma principal crea dinámicamente tramas consigo mismo. Pude crear la forma principal de la aplicación como prueba en el formulario de prueba y acceder a sus elementos de menú, etc.Prueba DUnit GUI: ¿Puedo forzar 'Aplicación' a una "forma" diferente?

El problema surge cuando la aplicación intenta crear un marco de forma dinámica. La lectura de recursos del marco llega a un punto donde necesita el identificador de ventana (en mi caso, establecer el título de una hoja de pestaña). Aquí va de TWinControl.GetHandle a TWinControl.CreateWnd y a TCustomFrame.CreateParams.

En esta CreateParams, el código dice:

if Parent = nil then 
    Params.WndParent := Application.Handle; 

Aquí es donde se produce la diferencia. Cuando ejecuto la aplicación real (no en la prueba), Application.Handle aquí devuelve un número distinto de cero y el flujo continúa bien. Sin embargo, en la aplicación de prueba DUnit, la Application.Handle aquí devuelve 0. Esto hace que el código en el TWinControl.CreateWnd a lanzar una excepción diciendo que el marco no tiene un padre:

with Params do 
    begin 
    if (WndParent = 0) and (Style and WS_CHILD <> 0) then 
     if (Owner <> nil) and (csReading in Owner.ComponentState) and 
     (Owner is TWinControl) then 
     WndParent := TWinControl(Owner).Handle 
     else 
     raise EInvalidOperation.CreateFmt(SParentRequired, [Name]); 

me gustaría intente evitar este problema (y, en general, todos los problemas de prueba) sin modificar el código de "producción" solo por las pruebas. ¿Puede proporcionar alguna pista sobre si de alguna manera podría forzar la "Aplicación" a otra cosa, o de alguna otra manera solucionar este problema?

Al mirar el código, un posible otro escenario de solución podría ser intentar que el propietario (que es mi "MainForm" de la aplicación a prueba, es decir, cuyo identificador me gustaría tener) esté en csLectura de estado mientras se realiza esta creación de cuadro en la prueba, pero al menos inicialmente tampoco parece tan sencillo lograr que esto suceda.

+0

¿Tiene su dpr una aplicación.Inicializar? Tal vez esto establezca el control. – mjn

+0

Tanto mi aplicación de prueba como la aplicación real tienen la aplicación. Inicialice en sus dprs. Puedo tratar de pasar por las inicializaciones para ver si puedo encontrar un lugar donde Application.Handle está establecido en algo o no. – DelphiUser

+0

DUnit me parece que no es el mejor para probar una GUI. – GolezTrol

Respuesta

0

Gracias por todos los comentarios y respuestas! Creo que he resuelto los problemas, al menos los descubrieron hasta ahora. Resumiré mis hallazgos y la situación final a continuación (en caso de que alguien más encuentre útil algo de esto).

Tengo una clase de decorador de pruebas que hereda de TTestSetup, que contiene una referencia a un formulario ficticio (principal) que crea cuando es necesario.

También encontré una manera de conmutar el Application.MainForm en tiempo de ejecución utilizando el enfoque de esta manera: http://www.swissdelphicenter.ch/torry/showcode.php?id=665

En el método de ensayo decorador SetUp creo primera forma simulada y luego configurarlo como la principal forma de la Aplicación (esta configuración podría no ser necesaria aquí).

Luego tengo una clase de caso de prueba (que hereda de TGUITestCase), cuyo SetUp y TearDown se ejecutan para cada prueba. En esta Configuración, creo la forma principal que estoy probando y luego la configuro como la forma principal de la Aplicación. Luego, después de la prueba en TearDown del caso de prueba, configuro el formulario ficticio nuevamente para que sea la forma principal de la Aplicación, y solo después de esta llamada cierro y Libre a la forma principal que estoy probando. De lo contrario, se liberará un formulario que actualmente es la Aplicación. MainForm hará que finalice toda la aplicación DUnit.

+0

Si bien esto funciona para usted, sigue siendo un mal uso de TFrames. –

2

En lugar de trabajar en una forma de establecer Application.Handle, debe crear un TForm y establecer su frame.parent como ese TForm.

//Dunit Test Scaffolding code...Set up a workable environment for the test: 
aForm := TForm.Create(nil); 
aFrame := TFrame.Create(aForm); 
aFrame.Parent := aForm; 

En aplicaciones reales, marcos tendrán un padre (se criaron a una ventana, una TForm o TPanel por lo general). Está intentando decirle a un marco que se ejecute sin un padre, que TFrame no está diseñado para hacer.

+0

En realidad, no estoy tratando de decirle a un marco que se ejecute sin un padre, simplemente créelo. En mi aplicación real, los marcos se crean primero con la forma principal como Propietario. Luego, más adelante, cuando se realizan ciertas selecciones, se elige un marco adecuado según la selección y este marco se configura para que tenga su elemento principal como panel en el formulario principal. Por lo tanto, todos los marcos se mostrarán con el mismo elemento primario, uno a la vez, pero creado con anticipación. Todo esto sucede dentro de mi código de producción, que no quiero cambiar solo por el bien de la prueba. – DelphiUser

+0

No creo que TFrame esté diseñado para permitir lo que estás haciendo. Debería simplemente crear y acoplar un Formulario sin borde, y no tendrá tales problemas. Hay CERO BENEFICIO en hacer un marco en su caso. –

+0

Al usar marcos, no tengo que considerar ningún problema de acoplamiento, por lo que hay un beneficio distinto de cero, al menos para mí. – DelphiUser

Cuestiones relacionadas