NGUITestRunner.pas
上传用户:yjb1804
上传日期:2021-01-30
资源大小:3105k
文件大小:55k
源码类别:

Email服务器

开发平台:

Delphi

  1. { $Id: NGUITestRunner.pas,v 1.4 2006/07/19 02:45:55 judc Exp $ }
  2. {: DUnit: An XTreme testing framework for Delphi programs.
  3.    @author  The DUnit Group.
  4.    @version $Revision: 1.4 $ 2001/03/08 uberto
  5. }
  6. (*
  7.  * The contents of this file are subject to the Mozilla Public
  8.  * License Version 1.1 (the "License"); you may not use this file
  9.  * except in compliance with the License. You may obtain a copy of
  10.  * the License at http://www.mozilla.org/MPL/
  11.  *
  12.  * Software distributed under the License is distributed on an "AS
  13.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  14.  * implied. See the License for the specific language governing
  15.  * rights and limitations under the License.
  16.  *
  17.  * The Original Code is DUnit.
  18.  *
  19.  * The Initial Developers of the Original Code are Kent Beck, Erich Gamma,
  20.  * and Juancarlo A眅z.
  21.  * Portions created The Initial Developers are Copyright (C) 1999-2000.
  22.  * Portions created by The DUnit Group are Copyright (C) 2000-2004.
  23.  * All rights reserved.
  24.  *
  25.  * Contributor(s):
  26.  * Kent Beck <kentbeck@csi.com>
  27.  * Erich Gamma <Erich_Gamma@oti.com>
  28.  * Juanco A馿z <juanco@users.sourceforge.net>
  29.  * Chris Morris <chrismo@users.sourceforge.net>
  30.  * Jeff Moore <JeffMoore@users.sourceforge.net>
  31.  * Kenneth Semeijn <dunit@designtime.demon.nl>
  32.  * Uberto Barbini <uberto@usa.net>
  33.  * Brett Shearer <BrettShearer@users.sourceforge.net>
  34.  * Kris Golko <neuromancer@users.sourceforge.net>
  35.  * The DUnit group at SourceForge <http://dunit.sourceforge.net>
  36.  *
  37.  *)
  38. unit NGUITestRunner;
  39. interface
  40. uses
  41.   TestFramework,
  42.   Windows,
  43.   Math,
  44.   Graphics, Controls, Forms, Dialogs,
  45.   ComCtrls, ExtCtrls, StdCtrls, ImgList, Buttons, Menus, ActnList,
  46.   SysUtils, Classes, IniFiles, ToolWin, System.ComponentModel;
  47. const
  48.   {: Section of the dunit.ini file where GUI information will be stored }
  49.   cnConfigIniSection = 'GUITestRunner Config';
  50.   {: Color constants for the progress bar and failure details panel }
  51.   clOK      = clGreen;
  52.   clFAILURE = clFuchsia;
  53.   clERROR   = clRed;
  54.   {: Indexes of the color images used in the test tree and failure list }
  55.   imgNONE     = 0;
  56.   imgRUNNING  = 1;
  57.   imgRUN      = 2;
  58.   imgHASPROPS = 3;
  59.   imgFAILED   = 4;
  60.   imgERROR    = 5;
  61.   {: Indexes of the images used for test tree checkboxes }
  62.   imgDISABLED        = 1;
  63.   imgPARENT_DISABLED = 2;
  64.   imgENABLED         = 3;
  65. type
  66.   {: Function type used by the TDUnitDialog.ApplyToTests method
  67.      @param item  The ITest instance on which to act
  68.      @return true if processing should continue, false otherwise
  69.   }
  70.   TTestFunc = function (item :ITest):Boolean of object;
  71.   TGUITestRunner = class(TForm, ITestListener, ITestListenerX)
  72.     StateImages: TImageList;
  73.     RunImages: TImageList;
  74.     DialogActions: TActionList;
  75.     SelectAllAction: TAction;
  76.     DeselectAllAction: TAction;
  77.     SelectFailedAction: TAction;
  78.     MainMenu: TMainMenu;
  79.     TestTreeMenu: TMenuItem;
  80.     SelectAllItem: TMenuItem;
  81.     DeselectAllItem: TMenuItem;
  82.     SelectFailedItem: TMenuItem;
  83.     FileMenu: TMenuItem;
  84.     SaveConfigurationAction: TAction;
  85.     AutoSaveAction: TAction;
  86.     SaveConfigurationItem: TMenuItem;
  87.     AutoSaveItem: TMenuItem;
  88.     RestoreSavedAction: TAction;
  89.     RestoreSavedConfigurationItem: TMenuItem;
  90.     ViewMenu: TMenuItem;
  91.     HideErrorBoxItem: TMenuItem;
  92.     BodyPanel: TPanel;
  93.     ErrorBoxVisibleAction: TAction;
  94.     TopPanel: TPanel;
  95.     TreePanel: TPanel;
  96.     TestTree: TTreeView;
  97.     ResultsPanel: TPanel;
  98.     ProgressPanel: TPanel;
  99.     ResultsView: TListView;
  100.     FailureListView: TListView;
  101.     ErrorBoxPanel: TPanel;
  102.     ErrorBoxSplitter: TSplitter;
  103.     ResultsSplitter: TSplitter;
  104.     AutoChangeFocusItem: TMenuItem;
  105.     TopProgressPanel: TPanel;
  106.     ProgressBar: TProgressBar;
  107.     pnlProgresslabel: TPanel;
  108.     ScorePanel: TPanel;
  109.     ScoreLabel: TPanel;
  110.     ScoreBar: TProgressBar;
  111.     pmTestTree: TPopupMenu;
  112.     pmiSelectAll: TMenuItem;
  113.     pmiDeselectAll: TMenuItem;
  114.     pmiSelectFailed: TMenuItem;
  115.     HideTestNodesAction: TAction;
  116.     CollapseLowestSuiteNodesItem: TMenuItem;
  117.     CollapseLowestSuiteNodes1: TMenuItem;
  118.     HideTestNodesOnOpenAction: TAction;
  119.     HideTestNodesItem: TMenuItem;
  120.     ExpandAllNodesAction: TAction;
  121.     TestTreeMenuSeparator: TMenuItem;
  122.     ExpandAllItem: TMenuItem;
  123.     TestTreeLocalMenuSeparator: TMenuItem;
  124.     ExpandAll2: TMenuItem;
  125.     lblTestTree: TLabel;
  126.     RunAction: TAction;
  127.     ExitAction: TAction;
  128.     BreakOnFailuresAction: TAction;
  129.     BreakonFailuresItem: TMenuItem;
  130.     ShowTestedNodeAction: TAction;
  131.     SelectTestedNodeItem: TMenuItem;
  132.     ErrorMessagePopup: TPopupMenu;
  133.     CopyFailureMessage: TMenuItem;
  134.     CopyMessageToClipboardAction: TAction;
  135.     ActionsMenu: TMenuItem;
  136.     CopyMessagetoCllipboardItem: TMenuItem;
  137.     LbProgress: TLabel;
  138.     UseRegistryAction: TAction;
  139.     UseRegistryItem: TMenuItem;
  140.     ErrorMessageRTF: TRichEdit;
  141.     SelectCurrentAction: TAction;
  142.     DeselectCurrentAction: TAction;
  143.     SelectCurrent1: TMenuItem;
  144.     DeselectCurrent1: TMenuItem;
  145.     ActionsImages: TImageList;
  146.     CloseItem: TMenuItem;
  147.     RunItem: TMenuItem;
  148.     StopAction: TAction;
  149.     StopActionItem: TMenuItem;
  150.     ToolBar1: TToolBar;
  151.     SelectAllButton: TToolButton;
  152.     DeselectAllButton: TToolButton;
  153.     ToolButton1: TToolButton;
  154.     SelectFailedButton: TToolButton;
  155.     ToolButton2: TToolButton;
  156.     SelectCurrentButton: TToolButton;
  157.     DeselectCurrentButton: TToolButton;
  158.     ToolButton3: TToolButton;
  159.     ToolButton4: TToolButton;
  160.     ToolButton5: TToolButton;
  161.     Alt_R_RunAction: TAction;
  162.     Alt_S_StopAction: TAction;
  163.     N1: TMenuItem;
  164.     DeselectCurrent2: TMenuItem;
  165.     SelectCurrent2: TMenuItem;
  166.     N2: TMenuItem;
  167.     CopyProcnameToClipboardAction: TAction;
  168.     N3: TMenuItem;
  169.     Copytestnametoclipboard1: TMenuItem;
  170.     N4: TMenuItem;
  171.     Copytestnametoclipboard2: TMenuItem;
  172.     RunSelectedTestAction: TAction;
  173.     N5: TMenuItem;
  174.     Runcurrenttest1: TMenuItem;
  175.     N6: TMenuItem;
  176.     Runcurrenttest2: TMenuItem;
  177.     RunSelectedTestItem: TMenuItem;
  178.     RunSelectedTestButton: TToolButton;
  179.     GoToNextSelectedTestAction: TAction;
  180.     GoToPrevSelectedTestAction: TAction;
  181.     N7: TMenuItem;
  182.     GoToNextSelectedNode1: TMenuItem;
  183.     GoToPreviousSelectedNode1: TMenuItem;
  184.     N8: TMenuItem;
  185.     GoToNextSelectedNode2: TMenuItem;
  186.     GoToPreviousSelectedNode2: TMenuItem;
  187.     FailIfNoChecksExecuted: TMenuItem;
  188.     FailIfNoChecksExecutedAction: TAction;
  189.     TestCaseProperty: TPopupMenu;
  190.     TestCaseProperties: TMenuItem;
  191.     N10: TMenuItem;
  192.     FailNoCheckExecutedMenuItem: TMenuItem;
  193.     N11: TMenuItem;
  194.     TestCasePopup: TMenuItem;
  195.     ShowTestCaseswithRunTimeProperties: TMenuItem;
  196.     ShowTestCasesWithRunTimePropertiesAction: TAction;
  197.     N9: TMenuItem;
  198.     N12: TMenuItem;
  199.     TestCasePropertiesAction: TAction;
  200.     PropertyPopUpAction: TAction;
  201.     Previous1: TMenuItem;
  202.     Next1: TMenuItem;
  203.     RunSelectedTest1: TMenuItem;
  204.     RunSelectedTestAltAction: TAction;
  205.     N13: TMenuItem;
  206.     WarnOnFailTestOverrideAction: TAction;
  207.     WarnOnFailTestOverride: TMenuItem;
  208.     procedure WarnOnFailTestOverrideActionExecute(Sender: TObject);
  209.     procedure FormCreate(Sender: TObject);
  210.     procedure TestTreeClick(Sender: TObject);
  211.     procedure FailureListViewSelectItem(Sender: TObject; Item: TListItem;
  212.       Selected: Boolean);
  213.     procedure FailureListViewClick(Sender: TObject);
  214.     procedure TestTreeKeyPress(Sender: TObject; var Key: Char);
  215.     procedure SelectAllActionExecute(Sender: TObject);
  216.     procedure DeselectAllActionExecute(Sender: TObject);
  217.     procedure SelectFailedActionExecute(Sender: TObject);
  218.     procedure SaveConfigurationActionExecute(Sender: TObject);
  219.     procedure RestoreSavedActionExecute(Sender: TObject);
  220.     procedure AutoSaveActionExecute(Sender: TObject);
  221.     procedure ErrorBoxVisibleActionExecute(Sender: TObject);
  222.     procedure ErrorBoxSplitterMoved(Sender: TObject);
  223.     procedure ErrorBoxPanelResize(Sender: TObject);
  224.     procedure HideTestNodesActionExecute(Sender: TObject);
  225.     procedure HideTestNodesOnOpenActionExecute(Sender: TObject);
  226.     procedure ExpandAllNodesActionExecute(Sender: TObject);
  227.     procedure RunActionExecute(Sender: TObject);
  228.     procedure ExitActionExecute(Sender: TObject);
  229.     procedure BreakOnFailuresActionExecute(Sender: TObject);
  230.     procedure FormDestroy(Sender: TObject);
  231.     procedure ShowTestedNodeActionExecute(Sender: TObject);
  232.     procedure CopyMessageToClipboardActionExecute(Sender: TObject);
  233.     procedure UseRegistryActionExecute(Sender: TObject);
  234.     procedure RunActionUpdate(Sender: TObject);
  235.     procedure CopyMessageToClipboardActionUpdate(Sender: TObject);
  236.     procedure SelectCurrentActionExecute(Sender: TObject);
  237.     procedure DeselectCurrentActionExecute(Sender: TObject);
  238.     procedure StopActionExecute(Sender: TObject);
  239.     procedure StopActionUpdate(Sender: TObject);
  240.     procedure TestTreeChange(Sender: TObject; Node: TTreeNode);
  241.     procedure CopyProcnameToClipboardActionExecute(Sender: TObject);
  242.     procedure CopyProcnameToClipboardActionUpdate(Sender: TObject);
  243.     procedure RunSelectedTestActionExecute(Sender: TObject);
  244.     procedure RunSelectedTestActionUpdate(Sender: TObject);
  245.     procedure TestTreeMouseDown(Sender: TObject; Button: TMouseButton;
  246.       Shift: TShiftState; X, Y: Integer);
  247.     procedure GoToNextSelectedTestActionExecute(Sender: TObject);
  248.     procedure GoToPrevSelectedTestActionExecute(Sender: TObject);
  249.     procedure FormShow(Sender: TObject);
  250.     procedure FailIfNoChecksExecutedActionExecute(Sender: TObject);
  251.     procedure ShowTestCasesWithRunTimePropertiesActionExecute(
  252.       Sender: TObject);
  253.     procedure TestCasePropertiesActionExecute(Sender: TObject);
  254.     procedure Previous1Click(Sender: TObject);
  255.     procedure Next1Click(Sender: TObject);
  256.     procedure TestCasePropertiesMeasureItem(Sender: TObject;
  257.       ACanvas: TCanvas; var Width, Height: Integer);
  258.     procedure TestCasePropertiesDrawItem(Sender: TObject; ACanvas: TCanvas;
  259.       ARect: TRect; Selected: Boolean);
  260.     procedure FailNoCheckExecutedMenuItemDrawItem(Sender: TObject;
  261.       ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
  262.     procedure pmTestTreePopup(Sender: TObject);
  263.     procedure FailNoCheckExecutedMenuItemClick(Sender: TObject);
  264.     procedure RunSelectedTestAltActionExecute(Sender: TObject);
  265.     procedure Previous1DrawItem(Sender: TObject; ACanvas: TCanvas;
  266.       ARect: TRect; Selected: Boolean);
  267.     procedure RunSelectedTest1DrawItem(Sender: TObject; ACanvas: TCanvas;
  268.       ARect: TRect; Selected: Boolean);
  269.     procedure Next1DrawItem(Sender: TObject; ACanvas: TCanvas;
  270.       ARect: TRect; Selected: Boolean);
  271.   private
  272.     FNoCheckExecutedPtyOverridden: Boolean;
  273.     FPopupY: Integer;
  274.     FPopupX: Integer;
  275.     procedure ResetProgress;
  276.     procedure MenuLooksInactive(ACanvas: TCanvas; ARect: TRect; Selected: Boolean;
  277.       Title: string; TitlePosn: UINT; PtyOveridesGUI: boolean);
  278.     procedure MenuLooksActive(ACanvas: TCanvas; ARect: TRect; Selected: Boolean;
  279.       Title: string; TitlePosn: UINT);
  280.     function  GetPropertyName(const Caption: string): string;
  281.   protected
  282.     FSuite:         ITest;
  283.     FTestResult:    TTestResult;
  284.     FRunning:       Boolean;
  285.     FTests:         TInterfaceList;
  286.     FSelectedTests: TInterfaceList;
  287.     FTotalTime:     Int64;
  288.     FRunTimeStr:    string;
  289.     FNoChecksStr:   string;
  290.     procedure Setup;
  291.     procedure SetUpStateImages;
  292.     procedure SetSuite(value: ITest);
  293.     procedure ClearResult;
  294.     procedure DisplayFailureMessage(Item :TListItem);
  295.     procedure ClearFailureMessage;
  296.     function  AddFailureItem(failure: TTestFailure): TListItem;
  297.     procedure UpdateStatus(const fullUpdate:Boolean);
  298.     procedure FillTestTree(RootNode: TTreeNode; ATest: ITest); overload;
  299.     procedure FillTestTree(ATest: ITest);                      overload;
  300.     procedure UpdateNodeImage(node: TTreeNode);
  301.     procedure UpdateNodeState(node: TTreeNode);
  302.     procedure SetNodeState(node: TTreeNode; enabled :boolean);
  303.     procedure SwitchNodeState(node: TTreeNode);
  304.     procedure UpdateTestTreeState;
  305.     procedure MakeNodeVisible(node :TTreeNode);
  306.     procedure SetTreeNodeImage(Node :TTReeNode; imgIndex :Integer);
  307.     procedure SelectNode(node: TTreeNode);
  308.     function  NodeToTest(node :TTreeNode) :ITest;
  309.     function  TestToNode(test :ITest) :TTreeNode;
  310.     function  SelectedTest :ITest;
  311.     procedure ListSelectedTests;
  312.     function  EnableTest(test :ITest) : boolean;
  313.     function  DisableTest(test :ITest) : boolean;
  314.     procedure ApplyToTests(root :TTreeNode; const func :TTestFunc);
  315.     procedure EnableUI(enable :Boolean);
  316.     procedure RunTheTest(aTest: ITest);
  317.     procedure InitTree; virtual;
  318.     function  IniFileName :string;
  319.     function  GetIniFile( const FileName : string ) : tCustomIniFile;
  320.     procedure LoadRegistryAction;
  321.     procedure SaveRegistryAction;
  322.     procedure LoadFormPlacement;
  323.     procedure SaveFormPlacement;
  324.     procedure SaveConfiguration;
  325.     procedure LoadConfiguration;
  326.     procedure LoadSuiteConfiguration;
  327.     procedure AutoSaveConfiguration;
  328.     function NodeIsGrandparent(ANode: TTreeNode): boolean;
  329.     procedure CollapseNonGrandparentNodes(RootNode: TTreeNode);
  330.     procedure ProcessClickOnStateIcon;
  331.     procedure ClearStatusMessage;
  332.     procedure CopyTestNametoClipboard(ANode: TTreeNode);
  333.     procedure SetupCustomShortcuts;
  334.     function SelectNodeIfTestEnabled(ANode: TTreeNode): boolean;
  335.   public
  336.     {: implement the ITestListener interface }
  337.     procedure AddSuccess(test: ITest);
  338.     procedure AddError(failure: TTestFailure);
  339.     procedure AddFailure(failure: TTestFailure);
  340.     function  ShouldRunTest(test :ITest):boolean;
  341.     procedure StartSuite(suite: ITest); virtual;
  342.     procedure EndSuite(suite: ITest); virtual;
  343.     procedure StartTest(test: ITest); virtual;
  344.     procedure EndTest(test: ITest); virtual;
  345.     procedure TestingStarts;
  346.     procedure TestingEnds(TestResult :TTestResult);
  347.     procedure Status(test :ITest; const Msg :string);
  348.     procedure Warning(test :ITest; const Msg :string);
  349.     {: The test suite to be run in this runner }
  350.     property Suite: ITest read FSuite write SetSuite;
  351.     {: The result of the last test run }
  352.     property TestResult : TTestResult read FTestResult write FTestResult;
  353.     class procedure RunTest(test: ITest);
  354.     class procedure RunRegisteredTests;
  355.   end;
  356. procedure RunTest(test: ITest);
  357. procedure RunRegisteredTests;
  358. procedure RunTestModeless(test: ITest);
  359. procedure RunRegisteredTestsModeless;
  360. implementation
  361. uses
  362.   Registry, Clipbrd;
  363. {$BOOLEVAL OFF}  // Required or you'll get an AV
  364. {$R *.nfm}
  365. type
  366.   TProgressBarCrack = class(TProgressBar);
  367. procedure RunTest(test: ITest);
  368. begin
  369.   with TGUITestRunner.Create(nil) do
  370.   begin
  371.     try
  372.       Suite := test;
  373.       ShowModal;
  374.     finally
  375.       Free;
  376.     end;
  377.   end;
  378. end;
  379. procedure RunTestModeless(test: ITest);
  380. var
  381.   GUI :TGUITestRunner;
  382. begin
  383.   Application.CreateForm(TGUITestRunner, GUI);
  384.   GUI.Suite := test;
  385.   GUI.Show;
  386. end;
  387. procedure RunRegisteredTests;
  388. begin
  389.    RunTest(registeredTests)
  390. end;
  391. procedure RunRegisteredTestsModeless;
  392. begin
  393.    RunTestModeless(registeredTests)
  394. end;
  395. { TGUITestRunner }
  396. procedure TGUITestRunner.InitTree;
  397. begin
  398.   FTests.Clear;
  399.   FillTestTree(Suite);
  400.   Setup;
  401.   if HideTestNodesOnOpenAction.Checked then
  402.     HideTestNodesAction.Execute
  403.   else
  404.     ExpandAllNodesAction.Execute;
  405.   TestTree.Selected := TestTree.Items.GetFirstNode;
  406. end;
  407. function TGUITestRunner.NodeToTest(Node: TTreeNode): ITest;
  408. var
  409.   idx: Integer;
  410. begin
  411.   assert(assigned(Node));
  412.   idx  := Integer(Node.data);
  413.   assert((idx >= 0) and (idx < FTests.Count));
  414.   result := FTests[idx] as ITest;
  415. end;
  416. function TGUITestRunner.TestToNode(test: ITest): TTreeNode;
  417. begin
  418.   assert(assigned(test));
  419.   Result := test.GUIObject as TTreeNode;
  420.   assert(assigned(Result));
  421. end;
  422. function TGUITestRunner.ShouldRunTest(test: ITest): boolean;
  423. begin
  424.   if FSelectedTests = nil then
  425.     Result := test.Enabled
  426.   else
  427.     Result := FSelectedTests.IndexOf(test as ITest) >= 0;
  428. end;
  429. procedure TGUITestRunner.StartTest(test: ITest);
  430. var
  431.   node :TTreeNode;
  432. begin
  433.   assert(assigned(TestResult));
  434.   assert(assigned(test));
  435.   node := TestToNode(test);
  436.   assert(assigned(node));
  437.   SetTreeNodeImage(node, imgRunning);
  438.   if ShowTestedNodeAction.Checked then
  439.   begin
  440.     MakeNodeVisible(node);
  441.     TestTree.Update;
  442.   end;
  443.   ClearStatusMessage;
  444.   UpdateStatus(False);
  445. end;
  446. procedure TGUITestRunner.EndTest(test: ITest);
  447. begin
  448.   UpdateStatus(False);
  449. end;
  450. procedure TGUITestRunner.TestingStarts;
  451. begin
  452.   FTotalTime := 0;
  453.   UpdateStatus(True);
  454. //  TProgressBarCrack(ScoreBar).Color := clOK;
  455. //  TProgressBarCrack(ScoreBar).RecreateWnd;
  456. //  (ScoreBar as TProgressBarCrack).Color := clOK;
  457. //  (ScoreBar as TProgressBarCrack).RecreateWnd;
  458.   ScoreBar.color := clOk;
  459. end;
  460. procedure TGUITestRunner.AddSuccess(test: ITest);
  461. var
  462.   OverridesGUI: Boolean;
  463.   HasRunTimePropsSet: Boolean;
  464. begin
  465.   assert(assigned(test));
  466.   if not IsTestMethod(test) then
  467.     SetTreeNodeImage(TestToNode(Test), imgRun)
  468.   else
  469.   begin
  470.     OverridesGUI :=
  471.       ((FailIfNoChecksExecuted.Checked and not Test.FailsOnNoChecksExecuted));
  472.     HasRunTimePropsSet :=
  473.       ((Test.FailsOnNoChecksExecuted and not FailIfNoChecksExecuted.Checked));
  474.     if OverridesGUI then
  475.       FTestResult.Overrides := FTestResult.Overrides + 1;
  476.     if (WarnOnFailTestOverride.Checked and OverridesGUI) or
  477.        (ShowTestCaseswithRunTimeProperties.Checked and HasRunTimePropsSet) then
  478.       SetTreeNodeImage(TestToNode(Test), imgHASPROPS)
  479.     else
  480.       SetTreeNodeImage(TestToNode(Test), imgRun);
  481.   end;
  482. end;
  483. procedure TGUITestRunner.AddError(failure: TTestFailure);
  484. var
  485.   ListItem: TListItem;
  486. begin
  487.   ListItem := AddFailureItem(failure);
  488.   ListItem.ImageIndex := imgERROR;
  489. //  TProgressBarCrack(ScoreBar).Color := clERROR;
  490. //  TProgressBarCrack(ScoreBar).RecreateWnd;
  491.   ScoreBar.Color := clERROR;
  492.   SetTreeNodeImage(TestToNode(failure.failedTest), imgERROR);
  493.   UpdateStatus(False);
  494. end;
  495. procedure TGUITestRunner.AddFailure(failure: TTestFailure);
  496. var
  497.   ListItem: TListItem;
  498. begin
  499.   ListItem := AddFailureItem(failure);
  500.   ListItem.ImageIndex := imgFAILED;
  501.   if TestResult.errorCount = 0 then
  502.   begin
  503. //    TProgressBarCrack(ScoreBar).Color := clFAILURE;
  504. //    TProgressBarCrack(ScoreBar).RecreateWnd;
  505.     ScoreBar.Color := clFAILURE;
  506.   end;
  507.   SetTreeNodeImage(TestToNode(failure.failedTest), imgFAILED);
  508.   UpdateStatus(False);
  509. end;
  510. function TGUITestRunner.IniFileName: string;
  511. const
  512.   TEST_INI_FILE = 'dunit.ini';
  513. begin
  514.     result := ExtractFilePath(Application.ExeName) + TEST_INI_FILE
  515. end;
  516. procedure TGUITestRunner.LoadFormPlacement;
  517. begin
  518.   with GetIniFile( IniFileName ) do
  519.   try
  520.     Self.SetBounds(
  521.                    ReadInteger(cnConfigIniSection, 'Left',   Left),
  522.                    ReadInteger(cnConfigIniSection, 'Top',    Top),
  523.                    ReadInteger(cnConfigIniSection, 'Width',  Width),
  524.                    ReadInteger(cnConfigIniSection, 'Height', Height)
  525.                    );
  526.     if ReadBool(cnConfigIniSection, 'Maximized', False ) then
  527.       WindowState := wsMaximized;
  528.   finally
  529.     Free;
  530.   end;
  531. end;
  532. procedure TGUITestRunner.SaveFormPlacement;
  533. begin
  534.   with GetIniFile(IniFileName) do
  535.     try
  536.       WriteBool(cnConfigIniSection, 'AutoSave', AutoSaveAction.Checked);
  537.       if WindowState <> wsMaximized then
  538.       begin
  539.         WriteInteger(cnConfigIniSection, 'Left',   Left);
  540.         WriteInteger(cnConfigIniSection, 'Top',    Top);
  541.         WriteInteger(cnConfigIniSection, 'Width',  Width);
  542.         WriteInteger(cnConfigIniSection, 'Height', Height );
  543.       end;
  544.       WriteBool(cnConfigIniSection, 'Maximized', WindowState = wsMaximized );
  545.     finally
  546.       Free
  547.     end;
  548. end;
  549. procedure TGUITestRunner.LoadConfiguration;
  550. var
  551.   i :Integer;
  552. begin
  553.   LoadRegistryAction;
  554.   LoadFormPlacement;
  555.   LoadSuiteConfiguration;
  556.   with GetIniFile(IniFileName) do
  557.   try
  558.     with AutoSaveAction do
  559.       Checked := ReadBool(cnConfigIniSection, 'AutoSave', Checked);
  560.     { center splitter location }
  561.     with ResultsPanel do
  562.       Height := ReadInteger(cnConfigIniSection, 'ResultsPanel.Height', Height);
  563.     { error splitter location }
  564.     with ErrorBoxPanel do
  565.       Height := ReadInteger(cnConfigIniSection, 'ErrorMessage.Height', Height);
  566.     with ErrorBoxVisibleAction do
  567.       Checked := ReadBool(cnConfigIniSection, 'ErrorMessage.Visible', Checked);
  568.     ErrorBoxSplitter.Visible := ErrorBoxVisibleAction.Checked;
  569.     ErrorBoxPanel.Visible    := ErrorBoxVisibleAction.Checked;
  570.     { failure list configuration }
  571.     with FailureListView do begin
  572.       for i := 0 to Columns.Count-1 do
  573.       begin
  574.         Columns[i].Width := Max(4, ReadInteger(cnConfigIniSection,
  575.                                         Format('FailureList.ColumnWidth[%d]', [i]),
  576.                                         Columns[i].Width)
  577.                                         );
  578.       end;
  579.     end;
  580.     { other options }
  581.     HideTestNodesOnOpenAction.Checked := ReadBool(cnConfigIniSection,
  582.       'HideTestNodesOnOpen', HideTestNodesOnOpenAction.Checked);
  583.     BreakOnFailuresAction.Checked := ReadBool(cnConfigIniSection,
  584.       'BreakOnFailures', BreakOnFailuresAction.Checked);
  585.     FailIfNoChecksExecutedAction.Checked := ReadBool(cnConfigIniSection,
  586.       'FailOnNoChecksExecuted', FailIfNoChecksExecutedAction.Checked);
  587.     WarnOnFailTestOverrideAction.Checked := ReadBool(cnConfigIniSection,
  588.       'WarnOnFailTestOverride', WarnOnFailTestOverrideAction.Checked);
  589.     ShowTestedNodeAction.Checked := ReadBool(cnConfigIniSection,
  590.       'SelectTestedNode', ShowTestedNodeAction.Checked);
  591.     FPopupX := ReadInteger(cnConfigIniSection,'PopupX', 350);
  592.     FPopupY := ReadInteger(cnConfigIniSection,'PopupY', 30);
  593.   finally
  594.     Free;
  595.   end;
  596.   if Suite <> nil then
  597.     UpdateTestTreeState;
  598. end;
  599. procedure TGUITestRunner.AutoSaveConfiguration;
  600. begin
  601.   if AutoSaveAction.Checked then
  602.     SaveConfiguration;
  603. end;
  604. procedure TGUITestRunner.SaveConfiguration;
  605. var
  606.   i :Integer;
  607. begin
  608.   if Suite <> nil then
  609.     Suite.SaveConfiguration(IniFileName, UseRegistryAction.Checked, True);
  610.   SaveFormPlacement;
  611.   SaveRegistryAction;
  612.   with GetIniFile(IniFileName) do
  613.   try
  614.     { center splitter location }
  615.     WriteInteger(cnConfigIniSection, 'ResultsPanel.Height',
  616.       ResultsPanel.Height);
  617.     { error box }
  618.     WriteInteger(cnConfigIniSection, 'ErrorMessage.Height',
  619.       ErrorBoxPanel.Height);
  620.     WriteBool(cnConfigIniSection, 'ErrorMessage.Visible',
  621.       ErrorBoxVisibleAction.Checked);
  622.     { failure list configuration }
  623.     with FailureListView do begin
  624.       for i := 0 to Columns.Count-1 do
  625.       begin
  626.        WriteInteger( cnConfigIniSection,
  627.                      Format('FailureList.ColumnWidth[%d]', [i]),
  628.                      Columns[i].Width);
  629.       end;
  630.     end;
  631.     { other options }
  632.     WriteBool(cnConfigIniSection, 'HideTestNodesOnOpen',      HideTestNodesOnOpenAction.Checked);
  633.     WriteBool(cnConfigIniSection, 'BreakOnFailures',          BreakOnFailuresAction.Checked);
  634.     WriteBool(cnConfigIniSection, 'FailOnNoChecksExecuted',   FailIfNoChecksExecutedAction.Checked);
  635.     WriteBool(cnConfigIniSection, 'SelectTestedNode',         ShowTestedNodeAction.Checked);
  636.     WriteBool(cnConfigIniSection, 'WarnOnFailTestOverride',   WarnOnFailTestOverrideAction.Checked);
  637.     WriteInteger(cnConfigIniSection, 'PopupX',                FPopupX);
  638.     WriteInteger(cnConfigIniSection, 'PopupY',                FPopupY);
  639.   finally
  640.     Free;
  641.   end;
  642. end;
  643. procedure TGUITestRunner.TestingEnds(TestResult :TTestResult);
  644. begin
  645.   FTotalTime := TestResult.TotalTime;
  646. end;
  647. procedure TGUITestRunner.UpdateNodeState(node: TTreeNode);
  648. var
  649.   test: ITest;
  650. begin
  651.   assert(assigned(node));
  652.   test := NodeToTest(node);
  653.   assert(assigned(test));
  654.   UpdateNodeImage(node);
  655.   if node.HasChildren then
  656.   begin
  657.     node := node.getFirstChild;
  658.     while node <> nil do
  659.     begin
  660.       UpdateNodeState(node);
  661.       node := node.getNextSibling;
  662.     end;
  663.   end;
  664. end;
  665. procedure TGUITestRunner.SetNodeState(node: TTreeNode; enabled :boolean);
  666. var
  667.   MostSeniorChanged :TTReeNode;
  668. begin
  669.    assert(node <> nil);
  670.    // update ancestors if enabling
  671.    NodeToTest(Node).Enabled := enabled;
  672.    MostSeniorChanged := Node;
  673.    if enabled then
  674.    begin
  675.      while Node.Parent <> nil do
  676.      begin
  677.        Node := Node.Parent;
  678.        if not NodeToTest(Node).Enabled then
  679.        begin // changed
  680.           NodeToTest(Node).Enabled := true;
  681.           MostSeniorChanged := Node;
  682.           UpdateNodeImage(Node);
  683.        end
  684.      end;
  685.    end;
  686.    TestTree.Items.BeginUpdate;
  687.    try
  688.      UpdateNodeState(MostSeniorChanged);
  689.    finally
  690.      TestTree.Items.EndUpdate;
  691.    end
  692. end;
  693. procedure TGUITestRunner.SwitchNodeState(node: TTreeNode);
  694. begin
  695.    assert(node <> nil);
  696.    SetNodeState(node, not NodeToTest(node).enabled);
  697. end;
  698. procedure TGUITestRunner.UpdateTestTreeState;
  699. var
  700.   node :TTreeNode;
  701. begin
  702.   if TestTree.Items.Count > 0 then
  703.   begin
  704.     TestTree.Items.BeginUpdate;
  705.     try
  706.       node := TestTree.Items.GetFirstNode;
  707.       while node <> nil do
  708.       begin
  709.         UpdateNodeState(node);
  710.         node := node.getNextSibling;
  711.       end
  712.     finally
  713.       TestTree.Items.EndUpdate;
  714.     end;
  715.   end;
  716. end;
  717. procedure TGUITestRunner.UpdateStatus(const fullUpdate:Boolean);
  718. var
  719.   i :Integer;
  720.   TestNumber: Integer;
  721.    function FormatElapsedTime(milli: Int64):string;
  722.    var
  723.      h,nn,ss,zzz: Cardinal;
  724.    begin
  725.      h := milli div 3600000;
  726.      milli := milli mod 3600000;
  727.      nn := milli div 60000;
  728.      milli := milli mod 60000;
  729.      ss := milli div 1000;
  730.      milli := milli mod 1000;
  731.      zzz := milli;
  732.      Result := Format('%d:%2.2d:%2.2d.%3.3d', [h, nn, ss, zzz]);
  733.    end;
  734. begin
  735. // ATTENTION
  736. // when called first time after ShowModal the ResultView doesn't contain any items
  737.   if ResultsView.Items.Count = 0 then
  738.     Exit;
  739.   if fullUpdate then
  740.     if Assigned(Suite) then
  741.       ResultsView.Items[0].SubItems[0] := IntToStr(Suite.countEnabledTestCases)
  742.     else
  743.       ResultsView.Items[0].SubItems[0] := '';
  744.   if TestResult <> nil then
  745.   begin
  746.     // Save the test number as we use it a lot
  747.     TestNumber := TestResult.runCount;
  748.     // Only update every 8 tests to speed things up considerably
  749.     if fullUpdate or ((TestNumber and 7) = 0) then
  750.     begin
  751.       with ResultsView.Items[0] do
  752.       begin
  753.         SubItems[1] := IntToStr(TestNumber);
  754.         SubItems[2] := IntToStr(TestResult.failureCount);
  755.         SubItems[3] := IntToStr(TestResult.errorCount);
  756.         SubItems[4] := IntToStr(TestResult.Overrides);
  757.         SubItems[5] := FormatElapsedTime(TestResult.TotalTime);
  758.         SubItems[6] := FormatElapsedTime(max(TestResult.TotalTime, FTotalTime));
  759.       end;
  760.       with TestResult do
  761.       begin
  762.         ScoreBar.Position  := TestNumber - (failureCount + errorCount);
  763.         ProgressBar.Position := TestNumber;
  764.         // There is a possibility for zero tests
  765.         if (TestNumber = 0) and (Suite.CountEnabledTestCases = 0) then
  766.           LbProgress.Caption := '100%'
  767.         else
  768.           LbProgress.Caption := IntToStr((100 * ScoreBar.Position) div ScoreBar.Max) + '%';
  769.       end;
  770.     end;
  771.     // Allow the display to catch up and check for key strokes
  772.     Application.ProcessMessages;
  773.   end
  774.   else
  775.   begin
  776.     with ResultsView.Items[0] do
  777.     begin
  778.       if (SubItems[0] = '0') or (subItems[0] = '') then
  779.       begin
  780.         for i := 1 to 6 do
  781.           SubItems[i] := ''
  782.       end
  783.       else
  784.       begin
  785.         if SubItems[0] <> subItems[1] then
  786.           for i := 1 to 6 do
  787.             SubItems[i] := ''
  788.         else
  789.         begin
  790.           SubItems[5] := FormatElapsedTime(SelectedTest.ElapsedTestTime);
  791.           SubItems[6] := FormatElapsedTime(Max(SelectedTest.ElapsedTestTime, FTotalTime));
  792.         end;
  793.       end;
  794.     end;
  795.     ResetProgress;
  796.   end;
  797.   if fullUpdate then
  798.     Update;
  799. end;
  800. procedure TGUITestRunner.ResetProgress;
  801. begin
  802. //  TProgressBarCrack(ScoreBar).ParentColor := True;
  803. //  TProgressBarCrack(ScoreBar).RecreateWnd;
  804.   ScoreBar.Position := 0;
  805.   ProgressBar.Position := 0;
  806.   LbProgress.Caption := '';
  807. end;
  808. function TGUITestRunner.AddFailureItem(failure: TTestFailure): TListItem;
  809. var
  810.   item : TListItem;
  811.   node : TTreeNode;
  812. begin
  813.   assert(assigned(failure));
  814.   item := FailureListView.Items.Add;
  815.   item.data := (TestToNode(failure.failedTest));
  816.   item.Caption := failure.failedTest.Name;
  817.   item.SubItems.Add(failure.thrownExceptionName);
  818.   item.SubItems.Add(failure.thrownExceptionMessage);
  819.   item.SubItems.Add( failure.LocationInfo
  820.                      + ' ' +
  821.                      failure.AddressInfo
  822.                      );
  823.   item.SubItems.Add(failure.StackTrace);
  824.   node := testToNode(failure.failedTest);
  825.   while node <> nil do
  826.   begin
  827.     node.Expand(false);
  828.     node := node.Parent;
  829.   end;
  830.   Result := item;
  831. end;
  832. procedure TGUITestRunner.FillTestTree(RootNode: TTreeNode; ATest: ITest);
  833. var
  834.   TestTests: IInterfaceList;
  835.   i: Integer;
  836. begin
  837.   if ATest = nil then
  838.     EXIT;
  839.   RootNode := TestTree.Items.AddChild(RootNode, ATest.Name);
  840.   RootNode.data := TObject(FTests.Add(ATest));
  841.   TestTests := ATest.Tests;
  842.   for i := 0 to TestTests.count - 1 do
  843.   begin
  844.     FillTestTree(RootNode, TestTests[i] as ITest);
  845.   end;
  846. end;
  847. procedure TGUITestRunner.FillTestTree(ATest: ITest);
  848. begin
  849.   TestTree.Items.Clear;
  850.   FTests.Clear;
  851.   fillTestTree(nil, Suite);
  852. end;
  853. procedure TGUITestRunner.SetTreeNodeImage(Node :TTReeNode; imgIndex :Integer);
  854. begin
  855.   while Node <> nil do
  856.   begin
  857.     if imgIndex > Node.ImageIndex then
  858.     begin
  859.        Node.ImageIndex    := imgIndex;
  860.        Node.SelectedIndex := imgIndex;
  861.     end;
  862.     if imgIndex = imgRunning then
  863.       Node := nil
  864.     else
  865.       Node := Node.Parent;
  866.   end;
  867. end;
  868. procedure TGUITestRunner.SetSuite(value: ITest);
  869. begin
  870.   FSuite := value;
  871.   if FSuite <> nil then
  872.   begin
  873.     LoadSuiteConfiguration;
  874.     EnableUI(True);
  875.     InitTree;
  876.   end
  877.   else
  878.     EnableUI(False)
  879. end;
  880. procedure TGUITestRunner.DisplayFailureMessage(Item: TListItem);
  881. var
  882.   hlColor :TColor;
  883.   Test    :ITest;
  884.   Status  :string;
  885. begin
  886.   TestTree.Selected := TTreeNode(Item.data);
  887.   Test := NodeToTest(TestTree.Selected);
  888.   hlColor := clFAILURE;
  889.   if Item.ImageIndex >= imgERROR then
  890.      hlColor := clERROR;
  891.   with ErrorMessageRTF do
  892.     begin
  893.       Clear;
  894.       SelAttributes.Size  := self.Font.Size;
  895.       SelAttributes.Style := [fsBold];
  896.       SelText := Item.Caption + ': ';
  897.       SelAttributes.Color := hlColor;
  898.       SelAttributes.Style := [fsBold];
  899.       SelText := Item.SubItems[0];
  900.       Lines.Add('');
  901.       SelAttributes.Color := clWindowText;
  902.       SelAttributes.Style := [];
  903.       SelText := 'at ' + Item.SubItems[2];
  904.       if Item.SubItems[1] <> '' then
  905.       begin
  906.         SelAttributes.Color := clWindowText;
  907.         Lines.Add('');
  908.         SelAttributes.Size  := 12;
  909.         SelAttributes.Style := [];
  910.         SelText := Item.SubItems[1];
  911.         SelAttributes.Size  := self.Font.Size;
  912.       end;
  913.       Status := Test.Status;
  914.       if Status <> '' then
  915.       begin
  916.         Lines.Add('');
  917.         Lines.Add('');
  918.         SelAttributes.Style := [fsBold];
  919.         Lines.Add('Status Messages');
  920.         SelAttributes.Style := [];
  921.         Lines.Add(Status);
  922.       end;
  923.       if Item.SubItems[3] <> '' then
  924.       begin
  925.         Lines.Add('');
  926.         SelAttributes.Style := [fsBold];
  927.         Lines.Add('StackTrace');
  928.         SelAttributes.Style := [];
  929.         SelText := Item.SubItems[3];
  930.       end;
  931.     end
  932. end;
  933. procedure TGUITestRunner.ClearFailureMessage;
  934. begin
  935.   ErrorMessageRTF.Clear;
  936. end;
  937. procedure TGUITestRunner.ClearResult;
  938. begin
  939.   if FTestResult <> nil then
  940.   begin
  941.     FTestResult.Free;
  942.     FTestResult := nil;
  943.     ClearFailureMessage;
  944.   end;
  945. end;
  946. procedure TGUITestRunner.SetUp;
  947. var
  948.   i: Integer;
  949.   node: TTreeNode;
  950. begin
  951.   FailureListView.Items.Clear;
  952.   ResetProgress;
  953.   Update;
  954.   with ResultsView.Items[0] do
  955.   begin
  956.     if Suite <> nil then
  957.     begin
  958.       SubItems[0] := IntToStr(Suite.countEnabledTestCases);
  959.     end
  960.     else
  961.     begin
  962.       SubItems[0] := '';
  963.     end;
  964.     SubItems[1] := '';
  965.     SubItems[2] := '';
  966.     SubItems[3] := '';
  967.     SubItems[4] := '';
  968.     SubItems[5] := '';
  969.     SubItems[6] := '';
  970.   end;
  971.   if Suite <> nil then
  972.   begin
  973.     ProgressBar.Max := Suite.countEnabledTestCases;
  974.   end
  975.   else
  976.   begin
  977.     ProgressBar.Max:= 10000;
  978.   end;
  979.   ScoreBar.Max := ProgressBar.Max;
  980.   for i := 0 to TestTree.Items.Count - 1 do
  981.   begin
  982.     node := TestTree.Items[i];
  983.     node.ImageIndex    := imgNONE;
  984.     node.SelectedIndex := imgNONE;
  985.   end;
  986.   UpdateTestTreeState;
  987. end;
  988. procedure TGUITestRunner.EnableUI(enable: Boolean);
  989. begin
  990.   SelectAllAction.Enabled    := enable;
  991.   DeselectAllAction.Enabled  := enable;
  992.   SelectFailedAction.Enabled := enable;
  993.   SelectCurrentAction.Enabled := enable;
  994.   DeselectCurrentAction.Enabled := enable;
  995.   HideTestNodesAction.Enabled   := enable;
  996.   ExpandAllNodesAction.Enabled  := enable;
  997. end;
  998. procedure TGUITestRunner.FormCreate(Sender: TObject);
  999. begin
  1000.   inherited;
  1001.   FTests := TInterfaceList.Create;
  1002.   LoadConfiguration;
  1003.   TimeSeparator := ':';
  1004.   SetUpStateImages;
  1005.   SetupCustomShortcuts;
  1006.   TestTree.Items.Clear;
  1007.   EnableUI(false);
  1008.   ClearFailureMessage;
  1009.   Setup;
  1010. end;
  1011. procedure TGUITestRunner.FormDestroy(Sender: TObject);
  1012. begin
  1013.   ClearResult;
  1014.   AutoSaveConfiguration;
  1015.   Suite := nil;
  1016.   FTests.Free;
  1017.   FTests := nil;
  1018.   inherited;
  1019. end;
  1020. procedure TGUITestRunner.FormShow(Sender: TObject);
  1021. var
  1022.   node: TTreeNode;
  1023.   test: ITest;
  1024. begin
  1025.   // Set up the GUI nodes here because the tree and all its tree nodes get
  1026.   // recreated in TCustomForm.ShowModal in D8+ so we cannot do it sooner
  1027.   node := TestTree.Items.GetFirstNode;
  1028.   while assigned(node) do
  1029.   begin
  1030.     // Get and check the test for the tree node
  1031.     test := NodeToTest(node);
  1032.     assert(Assigned(test));
  1033.     // Save the tree node in the test and get the next tree node
  1034.     test.GUIObject := node;
  1035.     node := node.GetNext;
  1036.   end;
  1037. end;
  1038. procedure TGUITestRunner.TestTreeClick(Sender: TObject);
  1039. begin
  1040.   if FRunning then
  1041.     EXIT;
  1042.   ProcessClickOnStateIcon;
  1043.   TestTreeChange(Sender, TestTree.Selected);
  1044. end;
  1045. procedure TGUITestRunner.TestTreeChange(Sender: TObject; Node: TTreeNode);
  1046. var
  1047.   i : Integer;
  1048. begin
  1049.   if (Node <> nil) and (Node = TestTree.Selected) then
  1050.   begin
  1051.     FailureListView.Selected := nil;
  1052.     for i := 0 to FailureListView.Items.count - 1 do
  1053.     begin
  1054.       if TTreeNode(FailureListView.Items[i].Data) = Node then
  1055.       begin
  1056.         FailureListView.Selected := FailureListView.Items[i];
  1057.         break;
  1058.       end;
  1059.     end;
  1060.     UpdateStatus(True);
  1061.   end;
  1062. end;
  1063. procedure TGUITestRunner.FailureListViewClick(Sender: TObject);
  1064. begin
  1065.   if FailureListView.Selected <> nil then
  1066.   begin
  1067.     TestTree.Selected := TTreeNode(FailureListView.Selected.data);
  1068.   end;
  1069. end;
  1070. procedure TGUITestRunner.FailureListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
  1071. begin
  1072.   if not Selected then
  1073.     ClearFailureMessage
  1074.   else
  1075.     DisplayFailureMessage(Item);
  1076. end;
  1077. function TGUITestRunner.DisableTest(test: ITest): boolean;
  1078. begin
  1079.   test.enabled := false;
  1080.   result := true;
  1081. end;
  1082. function TGUITestRunner.EnableTest(test: ITest): boolean;
  1083. begin
  1084.   test.enabled := true;
  1085.   result := true;
  1086. end;
  1087. procedure TGUITestRunner.ApplyToTests(root :TTreeNode; const func :TTestFunc);
  1088.   procedure DoApply(rootnode :TTreeNode);
  1089.   var
  1090.     test: ITest;
  1091.     node: TTreeNode;
  1092.   begin
  1093.     if rootnode <> nil then
  1094.     begin
  1095.       test := NodeToTest(rootnode);
  1096.       if func(test) then
  1097.       begin
  1098.         node := rootnode.getFirstChild;
  1099.         while node <> nil do
  1100.         begin
  1101.           DoApply(node);
  1102.           node := node.getNextSibling;
  1103.         end;
  1104.       end;
  1105.     end;
  1106.   end;
  1107. begin
  1108.   TestTree.Items.BeginUpdate;
  1109.   try
  1110.     DoApply(root)
  1111.   finally
  1112.     TestTree.Items.EndUpdate
  1113.   end;
  1114.   UpdateTestTreeState;
  1115. end;
  1116. procedure TGUITestRunner.TestTreeKeyPress(Sender: TObject; var Key: Char);
  1117. begin
  1118.   if (Key = ' ') and (TestTree.Selected <> nil) then
  1119.   begin
  1120.     SwitchNodeState(TestTree.Selected);
  1121.     UpdateStatus(True);
  1122.     Key := #0
  1123.   end;
  1124. end;
  1125. procedure TGUITestRunner.SelectAllActionExecute(Sender: TObject);
  1126. begin
  1127.   ApplyToTests(TestTree.Items.GetFirstNode, EnableTest);
  1128.   UpdateStatus(True);
  1129. end;
  1130. procedure TGUITestRunner.DeselectAllActionExecute(Sender: TObject);
  1131. begin
  1132.   ApplyToTests(TestTree.Items.GetFirstNode, DisableTest);
  1133.   UpdateStatus(True);
  1134. end;
  1135. procedure TGUITestRunner.SelectFailedActionExecute(Sender: TObject);
  1136. var
  1137.   i: integer;
  1138.   ANode: TTreeNode;
  1139. begin
  1140.   { deselect all }
  1141.   ApplyToTests(TestTree.Items[0], DisableTest);
  1142.   { select failed }
  1143.   for i := 0 to FailureListView.Items.Count - 1 do
  1144.   begin
  1145.     ANode := TTreeNode(FailureListView.Items[i].Data);
  1146.     SetNodeState(ANode, true);
  1147.   end;
  1148.   UpdateStatus(True);
  1149. end;
  1150. procedure TGUITestRunner.SaveConfigurationActionExecute(Sender: TObject);
  1151. begin
  1152.   SaveConfiguration
  1153. end;
  1154. procedure TGUITestRunner.RestoreSavedActionExecute(Sender: TObject);
  1155. begin
  1156.   LoadConfiguration
  1157. end;
  1158. procedure TGUITestRunner.AutoSaveActionExecute(Sender: TObject);
  1159. begin
  1160.   with AutoSaveAction do
  1161.   begin
  1162.     Checked := not Checked
  1163.   end;
  1164.   AutoSaveConfiguration;
  1165. end;
  1166. procedure TGUITestRunner.ErrorBoxVisibleActionExecute(Sender: TObject);
  1167. begin
  1168.    with ErrorBoxVisibleAction do
  1169.    begin
  1170.      Checked := not Checked;
  1171.      ErrorBoxSplitter.Visible := Checked;
  1172.      ErrorBoxPanel.Visible    := Checked;
  1173.      if Checked then
  1174.      begin
  1175.       // Solve bugs with Delphi4 resizing with constraints
  1176.        ErrorBoxSplitter.Top := ErrorBoxPanel.Top-8;
  1177.      end
  1178.    end;
  1179. end;
  1180. procedure TGUITestRunner.ErrorBoxSplitterMoved(Sender: TObject);
  1181. begin
  1182.   // Solve bugs with Delphi4 resizing with constraints
  1183.   ErrorBoxSplitter.Top := ErrorBoxPanel.Top-8;
  1184.   self.Update;
  1185. end;
  1186. procedure TGUITestRunner.ErrorBoxPanelResize(Sender: TObject);
  1187. begin
  1188.   // Solve bugs with Delphi4 resizing with constraints
  1189.   ErrorBoxSplitter.Top := ErrorBoxPanel.Top-8;
  1190. end;
  1191. function TGUITestRunner.NodeIsGrandparent(ANode: TTreeNode): boolean;
  1192. var
  1193.   AChildNode: TTreeNode;
  1194. begin
  1195.   Result := false;
  1196.   if ANode.HasChildren then
  1197.   begin
  1198.     AChildNode := ANode.GetFirstChild;
  1199.     while AChildNode <> nil do
  1200.     begin
  1201.       Result := AChildNode.HasChildren or Result;
  1202.       AChildNode := ANode.GetNextChild(AChildNode);
  1203.     end;
  1204.   end;
  1205. end;
  1206. procedure TGUITestRunner.CollapseNonGrandparentNodes(RootNode: TTreeNode);
  1207. var
  1208.   AChildNode: TTreeNode;
  1209. begin
  1210.   if not NodeIsGrandparent(RootNode) then
  1211.     RootNode.Collapse(false);
  1212.   AChildNode := RootNode.GetFirstChild;
  1213.   while AChildNode <> nil do
  1214.   begin
  1215.     CollapseNonGrandparentNodes(AChildNode);
  1216.     AChildNode := RootNode.GetNextChild(AChildNode);
  1217.   end;
  1218. end;
  1219. procedure TGUITestRunner.HideTestNodesActionExecute(Sender: TObject);
  1220. var
  1221.   ANode: TTreeNode;
  1222. begin
  1223.   inherited;
  1224.   if TestTree.Items.Count = 0 then
  1225.     EXIT;
  1226.   TestTree.Items.BeginUpdate;
  1227.   try
  1228.     ANode := TestTree.Items[0];
  1229.     if ANode <> nil then
  1230.     begin
  1231.       ANode.Expand(true);
  1232.       CollapseNonGrandparentNodes(ANode);
  1233.       SelectNode(ANode);
  1234.     end;
  1235.   finally
  1236.     TestTree.Items.EndUpdate;
  1237.   end;
  1238. end;
  1239. procedure TGUITestRunner.HideTestNodesOnOpenActionExecute(Sender: TObject);
  1240. begin
  1241.   HideTestNodesOnOpenAction.Checked := not HideTestNodesOnOpenAction.Checked;
  1242. end;
  1243. procedure TGUITestRunner.ExpandAllNodesActionExecute(Sender: TObject);
  1244. begin
  1245.   TestTree.FullExpand;
  1246.   if (TestTree.Selected <> nil) then
  1247.     MakeNodeVisible(TestTree.Selected)
  1248.   else if(TestTree.Items.Count > 0) then
  1249.     TestTree.Selected := TestTree.Items[0];
  1250. end;
  1251. procedure TGUITestRunner.RunTheTest(aTest : ITest);
  1252. begin
  1253.   if aTest = nil then
  1254.     EXIT;
  1255.   if FRunning then
  1256.   begin
  1257.     // warning: we're reentering this method if FRunning is true
  1258.     assert(FTestResult <> nil);
  1259.     FTestResult.Stop;
  1260.     EXIT;
  1261.   end;
  1262.   FRunning := true;
  1263.   try
  1264.     RunAction.Enabled  := False;
  1265.     StopAction.Enabled := True;
  1266.     CopyMessageToClipboardAction.Enabled := false;
  1267.     EnableUI(false);
  1268.     AutoSaveConfiguration;
  1269.     ClearResult;
  1270.     TestResult := TTestResult.create;
  1271.     try
  1272.       TestResult.addListener(self);
  1273.       TestResult.BreakOnFailures := BreakOnFailuresAction.Checked;
  1274.       TestResult.FailsIfNoChecksExecuted := FailIfNoChecksExecutedAction.Checked;
  1275.       aTest.run(TestResult);
  1276.     finally
  1277.       TestResult.Free;
  1278.       TestResult := nil;
  1279.     end;
  1280.   finally
  1281.       FRunning := false;
  1282.       EnableUI(true);
  1283.   end;
  1284. end;
  1285. procedure TGUITestRunner.RunActionExecute(Sender: TObject);
  1286. begin
  1287.   if Suite = nil then
  1288.     EXIT;
  1289.   Setup;
  1290.   RunTheTest(Suite);
  1291. end;
  1292. procedure TGUITestRunner.ExitActionExecute(Sender: TObject);
  1293. begin
  1294.   if FTestResult <> nil then
  1295.      FTestResult.stop;
  1296.   self.ModalResult := mrCancel;
  1297.   Close;
  1298. end;
  1299. procedure TGUITestRunner.BreakOnFailuresActionExecute(Sender: TObject);
  1300. begin
  1301.   with BreakOnFailuresAction do
  1302.    Checked := not Checked;
  1303. end;
  1304. procedure TGUITestRunner.FailIfNoChecksExecutedActionExecute(Sender: TObject);
  1305. begin
  1306.   with FailIfNoChecksExecutedAction do
  1307.     Checked := not Checked;
  1308. end;
  1309. procedure TGUITestRunner.ShowTestCasesWithRunTimePropertiesActionExecute(
  1310.   Sender: TObject);
  1311. begin
  1312.   with ShowTestCasesWithRunTimePropertiesAction do
  1313.     Checked := not Checked;
  1314. end;
  1315. procedure TGUITestRunner.ShowTestedNodeActionExecute(Sender: TObject);
  1316. begin
  1317.   with ShowTestedNodeAction do
  1318.     Checked := not Checked;
  1319. end;
  1320. procedure TGUITestRunner.SetUpStateImages;
  1321. begin
  1322.     TestTree.Images             := RunImages;
  1323.     TestTree.StateImages        := StateImages;
  1324.     FailureListView.SmallImages := RunImages;
  1325. end;
  1326. procedure TGUITestRunner.LoadSuiteConfiguration;
  1327. begin
  1328.   if Suite <> nil then
  1329.     Suite.LoadConfiguration(IniFileName, UseRegistryAction.Checked, True);
  1330. end;
  1331. procedure TGUITestRunner.MakeNodeVisible(node: TTreeNode);
  1332. begin
  1333.   node.MakeVisible
  1334. end;
  1335. procedure TGUITestRunner.ProcessClickOnStateIcon;
  1336. var
  1337.   HitInfo: THitTests;
  1338.   node: TTreeNode;
  1339.   PointPos: TPoint;
  1340. begin
  1341.   GetCursorPos(PointPos);
  1342.   PointPos := TestTree.ScreenToClient(PointPos);
  1343.   with PointPos do
  1344.   begin
  1345.     HitInfo := TestTree.GetHitTestInfoAt(X, Y);
  1346.     node := TestTree.GetNodeAt(X, Y);
  1347.   end;
  1348.   if (node <> nil) and (HtOnStateIcon in HitInfo) then
  1349.   begin
  1350.     SwitchNodeState(node);
  1351.   end;
  1352. end;
  1353. procedure TGUITestRunner.UpdateNodeImage(node: TTreeNode);
  1354. var
  1355.   test :ITest;
  1356. begin
  1357.   test := NodeToTest(node);
  1358.   if not test.enabled then
  1359.   begin
  1360.     node.StateIndex := imgDISABLED;
  1361.   end
  1362.   else if (node.Parent <> nil)
  1363.   and (node.Parent.StateIndex <= imgPARENT_DISABLED) then
  1364.   begin
  1365.     node.StateIndex := imgPARENT_DISABLED;
  1366.   end
  1367.   else
  1368.   begin
  1369.     node.StateIndex := imgENABLED;
  1370.   end;
  1371. end;
  1372. procedure TGUITestRunner.CopyMessageToClipboardActionExecute(Sender: TObject);
  1373. begin
  1374.   ErrorMessageRTF.SelectAll;
  1375.   ErrorMessageRTF.CopyToClipboard;
  1376. end;
  1377. procedure TGUITestRunner.UseRegistryActionExecute(Sender: TObject);
  1378. begin
  1379.   with UseRegistryAction do
  1380.     Checked := not Checked;
  1381. end;
  1382. function TGUITestRunner.GetIniFile(const FileName: string) : tCustomIniFile;
  1383. begin
  1384.   if UseRegistryAction.Checked then
  1385.     Result := tRegistryIniFile.Create( GetDUnitRegistryKey + FileName )
  1386.   else
  1387.     Result := tIniFile.Create( FileName );
  1388. end;
  1389. procedure TGUITestRunner.LoadRegistryAction;
  1390. begin
  1391.   with TIniFile.Create(IniFileName) do
  1392.   try
  1393.     UseRegistryAction.Checked := ReadBool(cnConfigIniSection,
  1394.       'UseRegistry', UseRegistryAction.Checked);
  1395.   finally
  1396.     Free;
  1397.   end;
  1398. end;
  1399. procedure TGUITestRunner.SaveRegistryAction;
  1400. begin
  1401.   if UseRegistryAction.Checked then
  1402.     DeleteFile( IniFileName );
  1403.   with TIniFile.Create(IniFileName) do
  1404.   try
  1405.     WriteBool(cnConfigIniSection, 'UseRegistry', UseRegistryAction.Checked);
  1406.   finally
  1407.     Free;
  1408.   end;
  1409. end;
  1410. procedure TGUITestRunner.RunActionUpdate(Sender: TObject);
  1411. begin
  1412.   RunAction.Enabled := not FRunning and assigned( Suite ) and (Suite.countEnabledTestCases > 0);
  1413. end;
  1414. procedure TGUITestRunner.CopyMessageToClipboardActionUpdate(Sender: TObject);
  1415. begin
  1416.   CopyMessageToClipboardAction.Enabled := FailureListView.Selected <> nil;
  1417. end;
  1418. procedure TGUITestRunner.SelectCurrentActionExecute(Sender: TObject);
  1419. begin
  1420.   ApplyToTests(TestTree.Selected, EnableTest);
  1421.   SetNodeState(TestTree.Selected, true);
  1422.   UpdateStatus(True);
  1423. end;
  1424. procedure TGUITestRunner.DeselectCurrentActionExecute(Sender: TObject);
  1425. begin
  1426.   ApplyToTests(TestTree.Selected, DisableTest);
  1427.   UpdateStatus(True);
  1428. end;
  1429. procedure TGUITestRunner.StopActionExecute(Sender: TObject);
  1430. begin
  1431.   if FTestResult <> nil then
  1432.      FTestResult.stop;
  1433. end;
  1434. procedure TGUITestRunner.StopActionUpdate(Sender: TObject);
  1435. begin
  1436.   StopAction.Enabled := FRunning and (FTestResult <> nil);
  1437. end;
  1438. procedure TGUITestRunner.Status(test: ITest; const Msg: string);
  1439. begin
  1440.   if ErrorMessageRTF.Lines.Count = 0 then
  1441.     ErrorMessageRTF.Lines.Add(test.Name + ':');
  1442.   ErrorMessageRTF.Lines.Add(Msg);
  1443.   ErrorMessageRTF.Update;
  1444. end;
  1445. procedure TGUITestRunner.Warning(test: ITest; const Msg: string);
  1446. begin
  1447.   if ErrorMessageRTF.Lines.Count = 0 then
  1448.     ErrorMessageRTF.Lines.Add(test.Name + ':');
  1449.   ErrorMessageRTF.Lines.Add(Msg);
  1450.   ErrorMessageRTF.Update;
  1451. end;
  1452. procedure TGUITestRunner.WarnOnFailTestOverrideActionExecute(Sender: TObject);
  1453. begin
  1454.   with WarnOnFailTestOverrideAction do
  1455.     Checked := not Checked;
  1456. end;
  1457. procedure TGUITestRunner.ClearStatusMessage;
  1458. begin
  1459.   ErrorMessageRTF.Lines.Clear;
  1460. end;
  1461. procedure TGUITestRunner.CopyProcnameToClipboardActionExecute(
  1462.   Sender: TObject);
  1463. begin
  1464.   CopyTestNametoClipboard(TestTree.Selected);
  1465. end;
  1466. procedure TGUITestRunner.CopyTestNametoClipboard(ANode: TTreeNode);
  1467. begin
  1468.   if Assigned(ANode) then
  1469.   begin
  1470.     Clipboard.AsText := ANode.Text;
  1471.   end;
  1472. end;
  1473. procedure TGUITestRunner.CopyProcnameToClipboardActionUpdate(
  1474.   Sender: TObject);
  1475. begin
  1476.   (Sender as TAction).Enabled := Assigned(TestTree.Selected)
  1477.                                  and isTestMethod(NodeToTest(TestTree.Selected));
  1478. end;
  1479. function TGUITestRunner.SelectedTest: ITest;
  1480. begin
  1481.   if TestTree.Selected = nil then
  1482.     Result := nil
  1483.   else
  1484.     Result := NodeToTest(TestTree.Selected);
  1485. end;
  1486. procedure TGUITestRunner.ListSelectedTests;
  1487. var
  1488.   aTest: ITest;
  1489.   aNode: TTreeNode;
  1490. begin
  1491.   FSelectedTests.Free;
  1492.   FSelectedTests := nil;
  1493.   FSelectedTests := TInterfaceList.Create;
  1494.   aNode := TestTree.Selected;
  1495.   while Assigned(aNode) do
  1496.   begin
  1497.     aTest := NodeToTest(aNode);
  1498.     FSelectedTests.Add(aTest as ITest);
  1499.     aNode := aNode.Parent;
  1500.   end;
  1501. end;
  1502. procedure TGUITestRunner.RunSelectedTestActionExecute(Sender: TObject);
  1503. begin
  1504.   Setup;
  1505.   ListSelectedTests;
  1506.   ProgressBar.Max := 1;
  1507.   ScoreBar.Max    := 1;
  1508.   RunTheTest(Suite);
  1509.   {$IFDEF VER130}
  1510.     FreeAndNil(FSelectedTests);
  1511.   {$ELSE}
  1512.     FSelectedTests.Free;
  1513.     FSelectedTests := nil;
  1514.   {$ENDIF}
  1515. end;
  1516. procedure TGUITestRunner.RunSelectedTestActionUpdate(Sender: TObject);
  1517. var
  1518.   aTest :ITest;
  1519. begin
  1520.   ATest := SelectedTest;
  1521.   RunSelectedTestAction.Enabled := (aTest <> nil) and (aTest.CountTestCases = 1);
  1522. end;
  1523. class procedure TGUITestRunner.RunTest(test: ITest);
  1524. var
  1525.   myform: TGUITestRunner;
  1526. begin
  1527.   Application.CreateForm(TGUITestRunner, MyForm);
  1528.   with MyForm do
  1529.   begin
  1530.     try
  1531.   suite := test;
  1532.       ShowModal;
  1533.     finally
  1534.       Free;
  1535.     end;
  1536.   end;
  1537. end;
  1538. class procedure TGUITestRunner.RunRegisteredTests;
  1539. begin
  1540.   RunTest(RegisteredTests);
  1541. end;
  1542. procedure TGUITestRunner.EndSuite(suite: ITest);
  1543. begin
  1544.   UpdateStatus(True);
  1545. end;
  1546. procedure TGUITestRunner.StartSuite(suite: ITest);
  1547. begin
  1548. end;
  1549. procedure TGUITestRunner.TestTreeMouseDown(Sender: TObject;
  1550.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1551. var
  1552.   NewNode: TTreeNode;
  1553. begin
  1554.   { a version of this code was in the pmTestTreePopup event, but it created
  1555.     an intermittent bug. OnPopup is executed if any of the ShortCut keys
  1556.     belonging to items on the popup menu are used. This caused weird behavior,
  1557.     with the selected node suddenly changing to whatever was under the mouse
  1558.     cursor (or AV-ing if the mouse cursor wasn't over the DUnit form) when
  1559.     the user executed one of the keyboard shortcuts.
  1560.     It was intermittent most likely because the ShortCuts belonged to
  1561.     Main Menu items as well (shared from the Action.ShortCut), and the bug
  1562.     dependended on the Popup menu items receiving the ShortCut Windows message
  1563.     first.
  1564.     This code ensures that node selection occurs prior to the popup menu
  1565.     appearing when the user right-clicks on a non-selected tree node. }
  1566.   if (Button = mbRight) and (htOnItem in TestTree.GetHitTestInfoAt(X, Y)) then
  1567.   begin
  1568.     NewNode := TestTree.GetNodeAt(X, Y);
  1569.     if TestTree.Selected <> NewNode then
  1570.       TestTree.Selected := NewNode;
  1571.   end;
  1572. end;
  1573. procedure TGUITestRunner.GoToNextSelectedTestActionExecute(
  1574.   Sender: TObject);
  1575. var
  1576.   aNode: TTreeNode;
  1577. begin
  1578.   if TestTree.Selected <> nil then
  1579.   begin
  1580.     aNode := TestTree.Selected.GetNext;
  1581.     while aNode <> nil do
  1582.     begin
  1583.       if SelectNodeIfTestEnabled(aNode) then
  1584.         break
  1585.       else
  1586.         aNode := aNode.GetNext;
  1587.     end;
  1588.   end;
  1589. end;
  1590. function TGUITestRunner.SelectNodeIfTestEnabled(ANode: TTreeNode): boolean;
  1591. var
  1592.   ATest: ITest;
  1593. begin
  1594.   ATest := NodeToTest(ANode);
  1595.   if (ATest.Enabled) and (IsTestMethod(ATest)) then
  1596.   begin
  1597.     Result := true;
  1598.     SelectNode(ANode);
  1599.   end
  1600.   else
  1601.     Result := false;
  1602. end;
  1603. procedure TGUITestRunner.GoToPrevSelectedTestActionExecute(
  1604.   Sender: TObject);
  1605. var
  1606.   aNode: TTreeNode;
  1607. begin
  1608.   if TestTree.Selected <> nil then
  1609.   begin
  1610.     aNode := TestTree.Selected.GetPrev;
  1611.     while aNode <> nil do
  1612.     begin
  1613.       if SelectNodeIfTestEnabled(aNode) then
  1614.         break
  1615.       else
  1616.         aNode := aNode.GetPrev;
  1617.     end;
  1618.   end;
  1619. end;
  1620. procedure TGUITestRunner.SelectNode(node: TTreeNode);
  1621. begin
  1622.   node.Selected := true;
  1623.   MakeNodeVisible(node);
  1624. end;
  1625. procedure TGUITestRunner.SetupCustomShortcuts;
  1626. begin
  1627.   { the following shortcuts are not offered as an option in the
  1628.     form designer, but can be set up here }
  1629.   GoToNextSelectedTestAction.ShortCut := ShortCut(VK_RIGHT, [ssCtrl]);
  1630.   GoToPrevSelectedTestAction.ShortCut := ShortCut(VK_LEFT, [ssCtrl]);
  1631. end;
  1632. const
  1633.   PopupTitle   = 'TestCase Run-Time Applied Properties';
  1634.   PopupPrevious= ' Previous';
  1635.   PopupRun     = ' Run Selected Test';
  1636.   PopupNext    = ' Next';
  1637.   NoChecksStrT = ' FailsOnNoChecksExecuted    := True ';
  1638.   NoChecksStrF = ' FailsOnNoChecksExecuted    := False';
  1639.   ByteStrEnd = 31;
  1640. procedure TGUITestRunner.TestCasePropertiesActionExecute(Sender: TObject);
  1641. var
  1642.   aNode: TTreeNode;
  1643.   ATest: ITest;
  1644. begin
  1645.   if TestTree.Selected <> nil then
  1646.   begin
  1647.     aNode := TestTree.Selected;
  1648.     if (aNode <> nil) then
  1649.     begin
  1650.       ATest := NodeToTest(ANode);
  1651.       if IsTestMethod(ATest) then
  1652.       begin
  1653.         if ATest.FailsOnNoChecksExecuted then
  1654.           FNoChecksStr := NoChecksStrT
  1655.         else
  1656.           FNoChecksStr := NoChecksStrF;
  1657.         fNoCheckExecutedPtyOverridden := FailIfNoChecksExecutedAction.Checked and
  1658.           (not ATest.FailsOnNoChecksExecuted);
  1659.         TestCaseProperty.Popup(Self.Left + FPopupX,Self.Top + FPopupY);
  1660.       end;
  1661.     end;
  1662.     ATest := nil;
  1663.   end;
  1664. end;
  1665. procedure TGUITestRunner.Previous1Click(Sender: TObject);
  1666. begin
  1667.   GoToPrevSelectedTestActionExecute(Self);
  1668.   TestCasePropertiesActionExecute(self);
  1669. end;
  1670. procedure TGUITestRunner.Next1Click(Sender: TObject);
  1671. begin
  1672.   GoToNextSelectedTestActionExecute(Self);
  1673.   TestCasePropertiesActionExecute(self);
  1674. end;
  1675. procedure TGUITestRunner.TestCasePropertiesMeasureItem(Sender: TObject;
  1676.   ACanvas: TCanvas; var Width, Height: Integer);
  1677. var
  1678.   ImageSize: TSize;
  1679. begin
  1680.   ACanvas.Font.Name := 'Courier New';
  1681.   ACanvas.Font.Size := 8;
  1682.   if GetTextExtentPoint32(ACanvas.Handle,
  1683.                           {PChar}(FNoChecksStr),
  1684.                           Length(FNoChecksStr),
  1685.                           ImageSize) then
  1686.   Width  := ImageSize.cx + 20;
  1687.   Height := ImageSize.cy + 4;
  1688. end;
  1689. procedure TGUITestRunner.MenuLooksInactive(ACanvas: TCanvas;
  1690.                                            ARect: TRect;
  1691.                                            Selected: Boolean;
  1692.                                            Title: string;
  1693.                                            TitlePosn: UINT;
  1694.                                            PtyOveridesGUI: boolean);
  1695. begin
  1696.   ACanvas.Font.Name := 'Courier New';
  1697.   ACanvas.Font.Size := 8;
  1698.   if Selected then
  1699.     ACanvas.Font.Color := clBlack;
  1700.   if PtyOveridesGUI then
  1701.     ACanvas.Brush.Color := clYellow
  1702.   else
  1703.     ACanvas.Brush.Color := TColor($C0FCC0);  //Sort of Moneygreen
  1704.   ACanvas.FillRect(ARect);
  1705.   DrawText(ACanvas.Handle,
  1706.            {PChar}(Title),
  1707.            Length(Title),
  1708.            ARect,
  1709.            DT_VCENTER or DT_SINGLELINE or DT_NOCLIP or DT_NOPREFIX or TitlePosn);
  1710. end;
  1711. procedure TGUITestRunner.MenuLooksActive(ACanvas: TCanvas;
  1712.                                          ARect: TRect;
  1713.                                          Selected: Boolean;
  1714.                                          Title: string;
  1715.                                          TitlePosn: UINT);
  1716. begin
  1717.   ACanvas.Font.Name := 'Courier New';
  1718.   ACanvas.Font.Size := 8;
  1719.   ACanvas.FillRect(ARect);
  1720.   DrawText(ACanvas.Handle,
  1721.            {PChar}(Title),
  1722.            Length(Title),
  1723.            ARect,
  1724.            DT_VCENTER or DT_SINGLELINE or DT_NOCLIP or DT_NOPREFIX or TitlePosn);
  1725. end;
  1726. procedure TGUITestRunner.TestCasePropertiesDrawItem(Sender: TObject;
  1727.   ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
  1728. begin
  1729.   MenuLooksInactive(ACanvas, ARect, Selected, PopupTitle, DT_CENTER, False);
  1730. end;
  1731. procedure TGUITestRunner.Previous1DrawItem(Sender: TObject;
  1732.   ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
  1733. begin
  1734.   MenuLooksActive(ACanvas, ARect, Selected, PopupPrevious, DT_LEFT);
  1735. end;
  1736. procedure TGUITestRunner.RunSelectedTest1DrawItem(Sender: TObject;
  1737.   ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
  1738. begin
  1739.   MenuLooksActive(ACanvas, ARect, Selected, PopupRun, DT_LEFT);
  1740. end;
  1741. procedure TGUITestRunner.Next1DrawItem(Sender: TObject; ACanvas: TCanvas;
  1742.   ARect: TRect; Selected: Boolean);
  1743. begin
  1744.   MenuLooksActive(ACanvas, ARect, Selected, PopupNext, DT_LEFT);
  1745. end;
  1746. procedure TGUITestRunner.FailNoCheckExecutedMenuItemDrawItem(
  1747.   Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
  1748. begin
  1749.   MenuLooksInactive(ACanvas, ARect, Selected, FNoChecksStr,
  1750.     DT_LEFT, fNoCheckExecutedPtyOverridden);
  1751. end;
  1752. procedure TGUITestRunner.pmTestTreePopup(Sender: TObject);
  1753. var
  1754.   aNode: TTreeNode;
  1755.   ATest: ITest;
  1756. begin
  1757.   if TestTree.Selected <> nil then
  1758.   begin
  1759.     aNode := TestTree.Selected;
  1760.     if (aNode <> nil) then
  1761.     begin
  1762.       ATest := NodeToTest(ANode);
  1763.       TestCasePopup.Enabled := IsTestMethod(ATest);
  1764.     end;
  1765.     ATest := nil;
  1766.   end;
  1767. end;
  1768. function TGUITestRunner.GetPropertyName(const Caption: string): string;
  1769. var
  1770.   TempStr: string;
  1771.   PosSpace: integer;
  1772. begin
  1773.   TempStr := Trim(Caption);
  1774.   PosSpace := Pos(' ',TempStr);
  1775.   if (PosSpace > 1)  then
  1776.     result := Copy(TempStr, 1, PosSpace-1);
  1777. end;
  1778. procedure TGUITestRunner.FailNoCheckExecutedMenuItemClick(Sender: TObject);
  1779. begin
  1780.   Clipboard.AsText := GetPropertyName(NoChecksStrT);
  1781. end;
  1782. procedure TGUITestRunner.RunSelectedTestAltActionExecute(Sender: TObject);
  1783. begin
  1784.   RunSelectedTestActionExecute(Self);
  1785.   TestCasePropertiesActionExecute(Self);
  1786. end;
  1787. end.