Domanda

Sto cercando di eseguire un test dell'unità GUI con Dunit su un'applicazione la cui forma principale crea frame dinamicamente. Sono stato in grado di creare la forma principale dell'applicazione-test come modulo nel caso di prova e accedere alle sue voci di menu ecc.

Il problema arriva quando l'applicazione cerca di creare un frame dinamicamente. La lettura delle risorse del frame arriva a un punto in cui ha bisogno dell'impugnatura della finestra (nel mio caso, impostando la didascalia di una scheda). Qui va da TwinControl.gethandle a TwinControl.createwnd e a tcustomframe.createParams.

In questo createparams, il codice dice:

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

È qui che si verifica la differenza. Quando eseguo l'applicazione effettiva (non nel test), l'applicazione.handle qui restituisce un numero diverso da zero e il flusso continua OK. Ma nell'applicazione del test DUNIT, l'applicazione.handle qui restituisce 0. Questo causa il codice nel TwinControl.createwnd per aumentare un'eccezione che dice che il frame non ha un genitore:

  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]);

Mi piacerebbe provare a aggirare questo problema (e in generale, tutti i problemi di test) senza modificare il codice di "produzione" solo a causa dei test. Puoi fornire qualche indizio sul fatto che potrei in qualche modo forzare la "applicazione" a qualcos'altro, o in qualche altro modo aggirare questo?

Guardando il codice, un possibile altro scenario di soluzione potrebbe essere quello di cercare di ottenere il proprietario (che è la mia "forma principale" dell'applicazione-test, cioè il cui manico vorrei avere) per essere nello stato di creazione Questa creazione di frame nel test, ma almeno inizialmente non sembra così semplice far sì che ciò accada.

È stato utile?

Soluzione 2

Grazie per tutti i commenti e le risposte! Credo di aver risolto i problemi, almeno quelli scoperti finora. Riassumerò le mie scoperte e la situazione finale di seguito (nel caso in cui qualcun altro avrebbe trovato uno di questi utili).

Ho una classe di decoratore di prova che eredita da TtestSetUp, che contiene un riferimento a una forma fittizia (principale) che crea quando necessario.

Ho anche trovato un modo per cambiare l'applicazione.Mainform in runtime usando approccio come questo: http://www.swissdelphicenter.ch/torry/showcode.php?id=665

Nel metodo di configurazione del decoratore di prova creo prima la forma fittizia e poi la imposta come forma principale dell'applicazione (questa impostazione potrebbe non essere necessaria qui).

Quindi ho una classe di test di prova (ereditando da TguiTestCase), la cui configurazione e smontaggio sono eseguiti per ogni test. In questa configurazione creo la forma principale che sto testando e quindi la imposta come modulo principale dell'applicazione. Quindi, dopo lo smontaggio del test nel caso del test, ho impostato di nuovo il modulo fittizio per essere la forma principale dell'applicazione, e solo dopo questa chiamata si chiude e gratuita alla forma principale che sto testando. Altrimenti liberazione di un modulo che è attualmente l'applicazione.Mainform causerebbe terminare l'intera applicazione DUNIT.

Altri suggerimenti

Invece di lavorare attorno a un modo per impostare Application.handle, è necessario creare un TFORM e impostare il tuo frame.

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

Nelle app reali, i frame avranno un genitore (essere genitore a una finestra, di solito un TFORM o TPanel). Stai cercando di dire a un frame da eseguire senza un genitore, cosa che TFRAME non è progettato per fare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top