Code Search for Developers
 
 
  

frmUnitTests.pas from pyscripter at Krugle


Show frmUnitTests.pas syntax highlighted

unit frmUnitTests;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, frmIDEDockWin, JvComponentBase, JvDockControlForm, ExtCtrls, ImgList,
  JvExControls, JvComponent, JvLinkLabel, TBXDkPanels, VirtualTrees,
  JvExExtCtrls, JvNetscapeSplitter, TBXStatusBars, TB2Item, TBXExtItems,
  TB2Dock, TB2Toolbar, TBX, StdCtrls, JvExStdCtrls, JvRichEdit, mbTBXJvRichEdit,
  ActnList, TBXThemes;

type
  TUnitTestWindowStatus = (utwEmpty, utwLoaded, utwRunning, utwRun);

  TUnitTestWindow = class(TIDEDockWindow)
    ExplorerDock: TTBXDock;
    ExplorerToolbar: TTBXToolbar;
    Panel1: TPanel;
    RunImages: TImageList;
    UnitTests: TVirtualStringTree;
    DialogActions: TActionList;
    actRun: TAction;
    actStop: TAction;
    actSelectAll: TAction;
    actDeselectAll: TAction;
    actSelectFailed: TAction;
    actRefresh: TAction;
    TBXItem1: TTBXItem;
    TBXSeparatorItem1: TTBXSeparatorItem;
    TBXItem2: TTBXItem;
    TBXItem3: TTBXItem;
    TBXItem4: TTBXItem;
    TBXSeparatorItem2: TTBXSeparatorItem;
    TBXItem6: TTBXItem;
    TBXItem7: TTBXItem;
    Panel2: TPanel;
    ErrorText: TmbTBXJvRichEdit;
    Label2: TLabel;
    ModuleName: TLabel;
    Splitter: TJvNetscapeSplitter;
    actExpandAll: TAction;
    actCollapseAll: TAction;
    TBXItem10: TTBXItem;
    TBXItem8: TTBXItem;
    TBXSeparatorItem7: TTBXSeparatorItem;
    actClearAll: TAction;
    TBXItem5: TTBXItem;
    lbFoundTests: TLabel;
    lblRunTests: TLabel;
    lblFailures: TLabel;
    Bevel1: TBevel;
    procedure UnitTestsDblClick(Sender: TObject);
    procedure actStopExecute(Sender: TObject);
    procedure actClearAllExecute(Sender: TObject);
    procedure actSelectFailedExecute(Sender: TObject);
    procedure UnitTestsChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
    procedure actRunExecute(Sender: TObject);
    procedure UnitTestsChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
    procedure actDeselectAllExecute(Sender: TObject);
    procedure actCollapseAllExecute(Sender: TObject);
    procedure actExpandAllExecute(Sender: TObject);
    procedure actSelectAllExecute(Sender: TObject);
    procedure UnitTestsGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle;
      var HintText: WideString);
    procedure UnitTestsGetImageIndex(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
      var Ghosted: Boolean; var ImageIndex: Integer);
    procedure UnitTestsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
    procedure UnitTestsInitChildren(Sender: TBaseVirtualTree;
      Node: PVirtualNode; var ChildCount: Cardinal);
    procedure UnitTestsInitNode(Sender: TBaseVirtualTree; ParentNode,
      Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure actRefreshExecute(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
    TestClasses : TStringList;
    TestSuite, TestResult : Variant;
  protected
    procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE;
    procedure UpdateActions; override;
  public
    { Public declarations }
    Status : TUnitTestWindowStatus;
    TestsRun, TestsFailed, TestErrors : integer;
    ElapsedTime : double;
    procedure ClearAll;
    procedure StartTest(Test: Variant);
    procedure StopTest(Test: Variant);
    procedure AddError(Test, Err: Variant);
    procedure AddFailure(Test, Err: Variant);
    procedure AddSuccess(Test: Variant);
    function SelectedTestCount : integer;
    function FindTestNode(Test : Variant) : PVirtualNode;
  end;

var
  UnitTestWindow: TUnitTestWindow;

implementation

uses uCommonFunctions, uHighlighterProcs, frmPyIDEMain, VarPyth, JvJVCLUtils,
  uEditAppIntfs, PythonEngine, frmPythonII, dmCommands, cPyBaseDebugger, JclSysUtils,
  cPyDebugger;

{$R *.dfm}

{ Indexes of the color images used in the test tree and failure list }

Type
  TTestStatus = (tsNotRun, tsRunning, tsRun, tsFailed, tsError);

  PNodeDataRec = ^TNodeDataRec;
  TNodeDataRec = record
  end;

Const
  FoundTestsLabel = 'Found %d test%s';
  RunTestsLabel = 'Ran %d test%s%s';
  ElapsedTimeFormat = ' in %.3fs';
  FailuresLabel = 'Failures/Errors : %d/%d';
{ TUnitTestWindow }

procedure TUnitTestWindow.TBMThemeChange(var Message: TMessage);
begin
  inherited;
  if Message.WParam = TSC_VIEWCHANGE then begin
    FGPanel.Color := CurrentTheme.GetItemColor(GetItemInfo('inactive'));
    Splitter.ButtonColor :=
      CurrentTheme.GetItemColor(GetItemInfo('inactive'));
    Splitter.ButtonHighlightColor :=
      CurrentTheme.GetItemColor(GetItemInfo('active'));
  end;
end;

procedure TUnitTestWindow.actRefreshExecute(Sender: TObject);
Var
  i, j, Index : integer;
  Editor : IEditor;
  UnitTest, Module, InnerTestSuite,
  TestCase : Variant;
  ClassName, TestName : string;
  SL : TStringList;
  Cursor : IInterface;
  PyTestCase : PPyObject;
  TestCount : integer;
begin
  ClearAll;
  Editor := PyIDEMainForm.GetActiveEditor;
  if Assigned(Editor) then begin
    Cursor := WaitCursor;

    ModuleName.Caption := 'Module: ' + Editor.FileTitle;
    ModuleName.Hint := Editor.FileName;

    Module := PyControl.ActiveInterpreter.ImportModule(Editor);
    UnitTest := Import('unittest');
    TestSuite := UnitTest.findTestCases(Module);
    //  This TestSuite contains a list of TestSuites
    //  each of which contains TestCases corresponding to
    //  a TestCase class in the module!!!
    TestCount := 0;
    for i := 0 to Len(TestSuite._tests) - 1 do begin
      InnerTestSuite := TestSuite._tests[i];
      for j := 0 to Len(InnerTestSuite._tests) - 1 do begin
        TestCase := InnerTestSuite._tests[j];
        //  set the TestStatus
        TestCase.testStatus := Ord(tsNotRun);
        TestCase.errMsg := '';
        TestCase.enabled := True;
        ClassName := TestCase.__class__.__name__;
        Index := TestClasses.IndexOf(ClassName);
        if Index < 0 then begin
          SL := TStringList.Create;
          Index := TestClasses.AddObject(ClassName, SL);
        end;
        PyTestCase := ExtractPythonObjectFrom(TestCase); // Store the TestCase PPyObject
        GetPythonEngine.Py_XINCREF(PyTestCase);

        // Python 2.4
        if GetPythonEngine.PyObject_HasAttrString(PyTestCase, '_testMethodName') = 1 then
          //Python 2.5
          TestName := TestCase._testMethodName
        else
          // earlier versions - hack to access a private variable!
          TestName := TestCase._TestCase__testMethodName;

        TStringList(TestClasses.Objects[Index]).AddObject(TestName, TObject(PyTestCase));
        Inc(TestCount);
      end;
    end;

    if TestCount = 0 then begin
      MessageDlg('No tests found!', mtWarning, [mbOK], 0);
      ClearAll;
    end else begin
      UnitTests.RootNodeCount := TestClasses.Count;
      UnitTests.ReinitNode(UnitTests.RootNode, True);
      lbFoundTests.Caption := Format(FoundTestsLabel, [TestCount, Iff(TestCount=1, '', 's')]);
      Status := utwLoaded;
    end;
  end;
end;

procedure TUnitTestWindow.FormActivate(Sender: TObject);
begin
  inherited;
  if not HasFocus then begin
    FGPanelEnter(Self);
    PostMessage(UnitTests.Handle, WM_SETFOCUS, 0, 0);
  end;
end;

procedure TUnitTestWindow.FormCreate(Sender: TObject);
begin
  inherited;
  UnitTests.NodeDataSize := SizeOf(TNodeDataRec);

  TestClasses := TStringList.Create;
  TestClasses.Sorted := True;
  TestClasses.Duplicates := dupError;

  Status := utwEmpty;
end;

procedure TUnitTestWindow.FormDestroy(Sender: TObject);
begin
  ClearAll;
  TestClasses.Free;
  inherited;
end;

procedure TUnitTestWindow.ClearAll;
Var
  i, j : integer;
  SL : TStringList;
  PyTestCase : PPyObject;
begin
  UnitTests.Clear;
  for i := 0 to TestClasses.Count - 1 do begin
    SL := TStringList(TestClasses.Objects[i]);
    for j := 0 to SL.Count - 1 do with GetPythonEngine do begin
      PyTestCase := PPyObject(SL.Objects[j]);
      Py_XDECREF(PyTestCase);
    end;
    SL.Free;
  end;
  TestClasses.Clear;
  VarClear(TestSuite);

  TestsRun := 0;
  TestsFailed := 0;
  TestErrors := 0;
  ElapsedTime := 0;
  lblRunTests.Caption := Format(RunTestsLabel, [TestsRun, Iff(TestsRun=1, '', 's'), '']);
  lblFailures.Caption := Format(FailuresLabel, [TestsFailed, TestErrors]);

  ModuleName.Caption := 'No Module Loaded';
  ModuleName.Hint := '';

  lbFoundTests.Caption := Format(FoundTestsLabel, [0, 's']);

  Status := utwEmpty;
end;

procedure TUnitTestWindow.UnitTestsInitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
  if UnitTests.GetNodeLevel(Node) = 0 then begin
    Node.CheckType := ctTriStateCheckBox;
    if TStringList(TestClasses.Objects[Node.Index]).Count > 0 then
      InitialStates := [ivsHasChildren, ivsExpanded]
    else
      InitialStates := []
  end else begin
    Node.CheckType := ctCheckBox;
    InitialStates := [];
  end;
  Node.CheckState := csCheckedNormal;
end;

procedure TUnitTestWindow.UnitTestsInitChildren(Sender: TBaseVirtualTree;
  Node: PVirtualNode; var ChildCount: Cardinal);
begin
  if UnitTests.GetNodeLevel(Node) = 0 then
    ChildCount := TStringList(TestClasses.Objects[Node.Index]).Count
  else
    ChildCount := 0;
end;

procedure TUnitTestWindow.UnitTestsGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
begin
  if UnitTests.GetNodeLevel(Node) = 0 then
    CellText := TestClasses[Node.Index]
  else
    CellText := TStringList(TestClasses.Objects[Node.Parent.Index])[Node.Index]
end;

procedure TUnitTestWindow.UnitTestsGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: Integer);
var
  PyTestCase, PytestStatus : PPyObject;
begin
  if not (Kind in [ikNormal, ikSelected]) then exit;
  if UnitTests.GetNodeLevel(Node) = 0 then begin
    if vsExpanded in Node.States then
      ImageIndex := 5
    else
      ImageIndex := 6;
  end else with GetPythonEngine do begin
    PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Parent.Index]).Objects[Node.Index]);
    PytestStatus := PyObject_GetAttrString(PyTestCase, 'testStatus');
    CheckError;
    ImageIndex := PyLong_AsLong(PytestStatus);
    Py_XDECREF(PytestStatus);
  end;
end;

procedure TUnitTestWindow.UnitTestsGetHint(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex;
  var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: WideString);
var
  PyTestCase : PPyObject;
  TestCase : Variant;
begin
  HintText := '';
  if UnitTests.GetNodeLevel(Node) = 0 then begin
    if Assigned(Node.FirstChild) then begin
      PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Index]).Objects[0]);
      TestCase := VarPythonCreate(PyTestCase);
      if not VarIsNone(TestCase.__doc__) then
        HintText := FormatDocString(TestCase.__doc__);
    end;
  end else with GetPythonEngine do begin
    PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Parent.Index]).Objects[Node.Index]);
    TestCase := VarPythonCreate(PyTestCase);
    if not VarIsNone(TestCase.shortDescription()) then
      HintText := TestCase.shortDescription();
  end;
end;

procedure TUnitTestWindow.UnitTestsChecked(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  PyTestCase : PPyObject;
  TestCase : Variant;
begin
  if UnitTests.GetNodeLevel(Node) = 1 then begin
    PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Parent.Index]).Objects[Node.Index]);
    TestCase := VarPythonCreate(PyTestCase);
    TestCase.enabled := Node.CheckState in [csCheckedNormal, csCheckedPressed];
  end;
end;

procedure TUnitTestWindow.actSelectAllExecute(Sender: TObject);
Var
  Node : PVirtualNode;
begin
   Node := UnitTests.RootNode^.FirstChild;
   while Assigned(Node) do begin
     UnitTests.CheckState[Node] := csCheckedNormal;
     Node := Node.NextSibling;
   end;
end;

procedure TUnitTestWindow.actDeselectAllExecute(Sender: TObject);
Var
  Node : PVirtualNode;
begin
   Node := UnitTests.RootNode^.FirstChild;
   while Assigned(Node) do begin
     UnitTests.CheckState[Node] := csUncheckedNormal;
     Node := Node.NextSibling;
   end;
end;

procedure TUnitTestWindow.actSelectFailedExecute(Sender: TObject);
Var
  PyTestCase : PPyObject;
  TestCase : Variant;
  ClassNode, TestCaseNode : PVirtualNode;
begin
  actDeselectAllExecute(Sender);

  ClassNode := UnitTests.RootNode^.FirstChild;
  while Assigned(ClassNode) do begin
    TestCaseNode := ClassNode.FirstChild;
    while Assigned(TestCaseNode) do begin
      PyTestCase :=
        PPyObject(TStringList(TestClasses.Objects[TestCaseNode.Parent.Index]).Objects[TestCaseNode.Index]);
      TestCase := VarPythonCreate(PyTestCase);
      if TTestStatus(TestCase.testStatus) in [tsFailed, tsError] then
         UnitTests.CheckState[TestCaseNode] := csCheckedNormal;
      TestCaseNode := TestCaseNode.NextSibling;
    end;
    ClassNode := ClassNode.NextSibling;
  end;
end;

procedure TUnitTestWindow.actExpandAllExecute(Sender: TObject);
begin
  UnitTests.FullExpand;
end;

procedure TUnitTestWindow.actCollapseAllExecute(Sender: TObject);
begin
  UnitTests.FullCollapse;
end;

procedure TUnitTestWindow.actRunExecute(Sender: TObject);
Var
  UnitTestModule, TempTestSuite : Variant;
  PyTestCase : PPyObject;
  TestCase : Variant;
  ClassNode, TestCaseNode : PVirtualNode;
  StartTime, StopTime, Freq : Int64;
begin
  // Only allow when PyControl.ActiveDebugger is inactive
  if PyControl.DebuggerState <> dsInactive then Exit;
  UnitTestModule := Import('unittest');

  //  Create a TempTestSuite that contains only the checked tests
  TempTestSuite := UnitTestModule.TestSuite();

  ClassNode := UnitTests.RootNode^.FirstChild;
  while Assigned(ClassNode) do begin
    TestCaseNode := ClassNode.FirstChild;
    while Assigned(TestCaseNode) do begin
      PyTestCase :=
        PPyObject(TStringList(TestClasses.Objects[TestCaseNode.Parent.Index]).Objects[TestCaseNode.Index]);
      TestCase := VarPythonCreate(PyTestCase);
      TestCase.testStatus := Ord(tsNotRun);
      TestCase.errMsg := '';
      if TestCase.enabled then
        TempTestSuite._tests.append(TestCase);
      TestCaseNode := TestCaseNode.NextSibling;
    end;
    ClassNode := ClassNode.NextSibling;
  end;

  TestsRun := 0;
  TestsFailed := 0;
  TestErrors := 0;
  ElapsedTime := 0;
  lblRunTests.Caption := Format(RunTestsLabel, [TestsRun, Iff(TestsRun=1, '', 's'), '']);
  lblFailures.Caption := Format(FailuresLabel, [TestsFailed, TestErrors]);

  Status := utwRunning;
  UpdateActions;
  PyIDEMainForm.DebuggerStateChange(Self, dsInactive, dsRunningNoDebug);
  Application.ProcessMessages;
  TestResult := InternalInterpreter.PyInteractiveInterpreter.IDETestResult();
  try
    QueryPerformanceCounter(StartTime);
    TempTestSuite.run(TestResult);
    QueryPerformanceCounter(StopTime);
  finally
    if QueryPerformanceFrequency(Freq) then
      ElapsedTime := (StopTime-StartTime) / Freq
    else
      ElapsedTime := 0;
    VarClear(TestResult);
    Status := utwRun;
    PyIDEMainForm.DebuggerStateChange(Self, dsRunningNoDebug, dsInactive);
    lblRunTests.Caption := Format(RunTestsLabel,
      [TestsRun, Iff(TestsRun=1, '', 's'), Format(ElapsedTimeFormat, [ElapsedTime])]);
  end;
end;

procedure TUnitTestWindow.AddFailure(Test, Err: Variant);
// Called from IDETestResult
Var
  TestCaseNode : PVirtualNode;
begin
  Test.testStatus := Ord(tsFailed);
  Test.errMsg := Err;
  TestCaseNode := FindTestNode(Test);
  if Assigned(TestCaseNode) then begin
    UnitTests.ScrollIntoView(TestCaseNode, True);
    UnitTests.Refresh;
  end;
  Inc(TestsFailed);
  lblFailures.Caption := Format(FailuresLabel, [TestsFailed, TestErrors]);
  Application.ProcessMessages;
end;

procedure TUnitTestWindow.AddSuccess(Test: Variant);
// Called from IDETestResult
Var
  TestCaseNode : PVirtualNode;
begin
  Test.testStatus := Ord(tsRun);
  TestCaseNode := FindTestNode(Test);
  if Assigned(TestCaseNode) then begin
    UnitTests.ScrollIntoView(TestCaseNode, True);
    UnitTests.Refresh;
  end;
  Application.ProcessMessages;
end;

procedure TUnitTestWindow.StopTest(Test: Variant);
// Called from IDETestResult
begin
  Inc(TestsRun);
  lblRunTests.Caption := Format(RunTestsLabel, [TestsRun, Iff(TestsRun=1, '', 's'), '']);
  Application.ProcessMessages;
end;

procedure TUnitTestWindow.StartTest(Test: Variant);
// Called from IDETestResult
Var
  TestCaseNode : PVirtualNode;
begin
  Test.testStatus := Ord(tsRunning);
  TestCaseNode := FindTestNode(Test);
  if Assigned(TestCaseNode) then begin
    UnitTests.ScrollIntoView(TestCaseNode, True);
    UnitTests.Refresh;
    Application.ProcessMessages;
  end;
end;

procedure TUnitTestWindow.AddError(Test, Err: Variant);
// Called from IDETestResult
Var
  TestCaseNode : PVirtualNode;
begin
  Test.testStatus := Ord(tsError);
  Test.errMsg := Err;
  TestCaseNode := FindTestNode(Test);
  if Assigned(TestCaseNode) then begin
    UnitTests.ScrollIntoView(TestCaseNode, True);
    UnitTests.Refresh;
  end;
  Inc(TestErrors);
  lblFailures.Caption := Format(FailuresLabel, [TestsFailed, TestErrors]);
  Application.ProcessMessages;
end;

function TUnitTestWindow.FindTestNode(Test: Variant): PVirtualNode;
Var
  PyTestCase : PPyObject;
  TestCase : Variant;
  ClassNode, TestCaseNode : PVirtualNode;
begin
  Result := nil;
  ClassNode := UnitTests.RootNode^.FirstChild;
  while Assigned(ClassNode) do begin
    TestCaseNode := ClassNode.FirstChild;
    while Assigned(TestCaseNode) do begin
      PyTestCase :=
        PPyObject(TStringList(TestClasses.Objects[TestCaseNode.Parent.Index]).Objects[TestCaseNode.Index]);
      TestCase := VarPythonCreate(PyTestCase);
      if VarIsSame(Test, TestCase) then begin
        Result := TestCaseNode;
        Break;
      end;
      TestCaseNode := TestCaseNode.NextSibling;
    end;
    ClassNode := ClassNode.NextSibling;
  end;
end;

procedure TUnitTestWindow.UnitTestsChange(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
Var
  PyTestCase : PPyObject;
  TestCase : Variant;
begin
  if Assigned(Node) and (vsSelected in Node.States) and
    (UnitTests.GetNodeLevel(Node) = 1) then
  begin
    PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Parent.Index]).Objects[Node.Index]);
    TestCase := VarPythonCreate(PyTestCase);
    ErrorText.Text := TestCase.errMsg;
  end else
    ErrorText.Text := '';
end;

procedure TUnitTestWindow.actClearAllExecute(Sender: TObject);
begin
  ClearAll;
end;

function TUnitTestWindow.SelectedTestCount: integer;
Var
  ClassNode, TestCaseNode : PVirtualNode;
begin
  Result := 0;
  ClassNode := UnitTests.RootNode^.FirstChild;
  while Assigned(ClassNode) do begin
    TestCaseNode := ClassNode.FirstChild;
    while Assigned(TestCaseNode) do begin
      if TestCaseNode.CheckState in [csCheckedNormal, csCheckedPressed] then
        Inc(Result);
      TestCaseNode := TestCaseNode.NextSibling;
    end;
    ClassNode := ClassNode.NextSibling;
  end;
end;

procedure TUnitTestWindow.UpdateActions;
Var
  Count : integer;
begin
  Count := SelectedTestCount;

  actRun.Enabled := (Status in [utwLoaded, utwRun]) and (Count > 0) and
    (PyControl.DebuggerState = dsInactive);

  actSelectAll.Enabled := Status in [utwLoaded, utwRun];
  actDeselectAll.Enabled := Status in [utwLoaded, utwRun];
  actSelectFailed.Enabled := Status = utwRun;

  actRefresh.Enabled := Status <> utwRunning;

  actExpandAll.Enabled := Status <> utwEmpty;
  actCollapseAll.Enabled := Status <> utwEmpty;

  actClearAll.Enabled := not (Status in [utwEmpty, utwRunning]);

  actStop.Enabled := Status = utwRunning;
  inherited;
end;

procedure TUnitTestWindow.actStopExecute(Sender: TObject);
begin
  if VarIsPython(TestResult) then
    TestResult.stop();
end;

procedure TUnitTestWindow.UnitTestsDblClick(Sender: TObject);
var
  InspectModule : Variant;
  Node : PVirtualNode;
  PyTestCase : PPyObject;
  TestCase, PythonObject : Variant;
  FileName, TestName : string;
  NodeLevel, LineNo : integer;
begin
  Node := UnitTests.HotNode;
  if Assigned(Node) then begin
    NodeLevel := UnitTests.GetNodeLevel(Node);
    if NodeLevel = 0 then
      Node := Node.FirstChild;
    if (NodeLevel > 1)  or not Assigned(Node) then Exit;
    PyTestCase := PPyObject(TStringList(TestClasses.Objects[Node.Parent.Index]).Objects[Node.Index]);
    TestCase := VarPythonCreate(PyTestCase);
    if NodeLevel = 0 then
      PythonObject := TestCase.__class__
    else begin
      if GetPythonEngine.PyObject_HasAttrString(PyTestCase, '_testMethodName') = 1 then
        //Python 2.5
        TestName := TestCase._testMethodName
      else
        // earlier versions - hack to access a private variable!
        TestName := TestCase._TestCase__testMethodName;
      PythonObject := BuiltinModule.getattr(TestCase, TestName);
    end;
    if VarIsPython(PythonObject) then begin
      InspectModule := Import('inspect');
      if InspectModule.ismethod(PythonObject) then begin
        FileName := InspectModule.getsourcefile(PythonObject);
        if FileName = 'None' then begin
          FileName := PythonObject.im_func.func_code.co_filename;
          if ExtractFileExt(FileName) <> '' then
            Exit;
          // otherwise it should be an unsaved file
          LineNo := PythonObject.im_func.func_code.co_firstlineno-1;
        end else
          LineNo := InspectModule.findsource(PythonObject).GetItem(1);
        PyIDEMainForm.ShowFilePosition(FileName, Succ(LineNo), 1);
      end;
    end;
  end;
end;

end.





See more files for this project here

pyscripter

PyScripter is a free and open-source Python Integrated Development Environment (IDE) created with the ambition to become competitive in functionality with commercial Windows-based IDEs available for other languages. Being built in a compiled language is rather snappier than some of the other Python IDEs and provides an extensive blend of features that make it a productive Python development environment.

Project homepage: http://code.google.com/p/pyscripter/
Programming language(s): Pascal
License: mit

  Components/
  FastMM4Options.inc
  Install.txt
  JvAppIniStorage.pas
  JvAppInst.pas
  JvAppStorage.pas
  JvChangeNotify.pas
  JvCreateProcess.pas
  JvDockControlForm.pas
  JvDockInfo.pas
  JvDockVSNetStyle.pas
  JvProgramVersionCheck.pas
  JvTabBar.pas
  JvThread.pas
  PyScripter Logo.bmp
  PyScripter.bdsproj
  PyScripter.bdsproj.local
  PyScripter.dpr
  PyScripter.ico
  PyScripter.res
  Readme.txt
  StoHtmlHelp.pas
  StringResources.pas
  SynCompletionProposal.pas
  SynEdit.pas
  SynEditKeyCmds.pas
  SynHighlighterPython.pas
  cCodeHint.pas
  cFilePersist.pas
  cFileSearch.pas
  cFileTemplates.pas
  cFindInFiles.pas
  cParameters.pas
  cPyBaseDebugger.pas
  cPyDebugger.pas
  cPyRemoteDebugger.pas
  cPythonSourceScanner.pas
  cRefactoring.pas
  cTools.pas
  dlgAboutPyScripter.dfm
  dlgAboutPyScripter.pas
  dlgAskParam.dfm
  dlgAskParam.pas
  dlgCodeTemplates.dfm
  dlgCodeTemplates.pas
  dlgCommandLine.dfm
  dlgCommandLine.pas
  dlgConfigureTools.dfm
  dlgConfigureTools.pas
  dlgConfirmReplace.dfm
  dlgConfirmReplace.pas
  dlgCustomParams.dfm
  dlgCustomParams.pas
  dlgCustomShortcuts.dfm
  dlgCustomShortcuts.pas
  dlgDirectoryList.dfm
  dlgDirectoryList.pas
  dlgExceptionMail.dfm
  dlgExceptionMail.pas
  dlgFileTemplates.dfm
  dlgFileTemplates.pas
  dlgFindInFiles.dfm
  dlgFindInFiles.pas
  dlgFindResultsOptions.dfm
  dlgFindResultsOptions.pas
  dlgNewFile.dfm
  dlgNewFile.pas
  dlgOptionsEditor.dfm
  dlgOptionsEditor.pas
  dlgPickList.dfm
  dlgPickList.pas
  dlgReplaceInFiles.dfm
  dlgReplaceInFiles.pas
  dlgReplaceText.dfm
  dlgReplaceText.pas
  dlgSearchText.dfm
  dlgSearchText.pas
  dlgSynEditOptions.dfm
  dlgSynEditOptions.pas
  dlgSynPageSetup.dfm
  dlgSynPageSetup.pas
  dlgSynPrintPreview.dfm
  dlgSynPrintPreview.pas
  dlgToDoOptions.dfm
  dlgToDoOptions.pas
  dlgToolProperties.dfm
  dlgToolProperties.pas
  dlgUnitTestWizard.dfm
  dlgUnitTestWizard.pas
  dmCommands.dfm
  dmCommands.pas
  frmBreakPoints.dfm
  frmBreakPoints.pas
  frmCallStack.dfm
  frmCallStack.pas
  frmCodeExplorer.dfm
  frmCodeExplorer.pas
  frmCommandOutput.dfm
  frmCommandOutput.pas
  frmDisassemlyView.dfm
  frmDisassemlyView.pas
  frmDocView.dfm
  frmDocView.pas
  frmEditor.dfm
  frmEditor.pas
  frmFileExplorer.dfm
  frmFileExplorer.pas
  frmFindResults.dfm
  frmFindResults.pas
  frmFunctionList.dfm
  frmFunctionList.pas
  frmIDEDockWin.dfm
  frmIDEDockWin.pas
  frmMessages.dfm
  frmMessages.pas
  frmPyIDEMain.dfm
  frmPyIDEMain.pas
  frmPythonII.dfm
  frmPythonII.pas
  frmRegExpTester.dfm
  frmRegExpTester.pas
  frmToDo.dfm
  frmToDo.pas
  frmUnitTests.dfm
  frmUnitTests.pas
  frmVariables.dfm
  frmVariables.pas
  frmWatches.dfm
  frmWatches.pas
  uCommonFunctions.pas
  uEditAppIntfs.pas
  uHighlighterProcs.pas
  uMMMXP_MainService.pas
  uParams.pas