2
votes

As is sometimes usual in visual applications, I have some code where data is maintained in a visual component (a TTreeView component). I'm refactoring the code and creating unit tests for the logic.

The only visual form in my test project is the GUITestRunner. In the future I plan to run the tests as a console application under a continuous integration server, so I won't have any form.

When I try to create a TTreeView widget without a parent and use it, I get the following error:

Control '' has no parent window

What's the best way to create the widget on my test suite SetUp method and destroy it in the TearDown? Is it possible to use a visual widget in a console application? I don't need to display it, or even process events. I just have to create child nodes and access the data.

I managed to make it work with an ugly hack, but I'd like to know if there is some standard practice.

Sure, in my sunny and distant future, I'll refactor the code of this 21 thousand lines form, all my data will be in beautiful data structures and these kind of tests won't be necessary, but now I need it.

2

2 Answers

6
votes

You need to create a hidden (i.e. non-visible) window to be the parent. Here is a sample console app that proves that this approach works.

program HiddenWindow;

{$APPTYPE CONSOLE}

uses
  SysUtils, Forms, StdCtrls;

var
  Form: TForm;

begin
  Form := TForm.Create(Application);
  with TListBox.Create(Form) do begin
    Parent := Form;
    Items.Add('test');//fails if the parent is not set
  end;
end.
4
votes

In unit tests, you test the core functionality of a unit (which is rather a piece of logic than an actual literal unit-file). GUI is usually not part of this process.

You can however create an invisible form and place invisible controls on it. [edit] See David's answer for a way to do that. [/edit] That way you may be able to test it. And you could use visual controls too. there are even test suites that can test visual controls by running some kind of prerecorded macro that fills in a form and pressed the right buttons.

But in fact this isn't the right way. GUI testing is different from Unit testing. The business logic should be seperated enough from your GUI to be able to test it alone, apart from the GUI and from other 'units'.

And 21 thousand lines isn't so much, is it? Got half a million lines here (alhough I wouldn't like needing to refactoring them either). :) Take it a step at a time. Refactor little pieces and write unit tests for each refactored piece. That way, you can keep your test for the future, because they will be usefull, even when all your code looks great and structured.