Approaches to Automatically Testing Visual Components - PowerPoint PPT Presentation

1 / 21
About This Presentation
Title:

Approaches to Automatically Testing Visual Components

Description:

Difficulties Using Dunit with Visual Components. Simulating User Interaction in DUnit ... Borland's private 'Zombie' program does something similar. ... – PowerPoint PPT presentation

Number of Views:134
Avg rating:3.0/5.0
Slides: 22
Provided by: richardb49
Category:

less

Transcript and Presenter's Notes

Title: Approaches to Automatically Testing Visual Components


1
Approaches to Automatically Testing Visual
Components
  • Richard B. Winston
  • CPCUG Programmers SIG
  • Nov. 1, 2006

2
Outline
  • Review of DUnit
  • Difficulties Using Dunit with Visual Components
  • Simulating User Interaction in DUnit
  • Comparing Appearances of Visual Components
  • Limitations

3
Review of DUnit
  • Testing Framework for Delphi
  • Open Source http//dunit.sourceforge.net/
  • Built-in support in BDS 2005 and 2006
  • Works with Delphi gt 5

4
DUnit Example 1
  • type
  • // Test methods for class TRbwParser
  • TestTRbwParser class(TTestCase)
  • strict private
  • FRbwParser TRbwParser
  • public
  • procedure SetUp override
  • procedure TearDown override
  • published
  • procedure TestClearExpressions
  • end

5
DUnit Example 2
  • procedure TestTRbwParser.TestClearExpressions
  • var
  • Expression string
  • begin
  • if FRbwParser.ExpressionCount 0 then
  • begin
  • Expression '12'
  • FRbwParser.Compile(Expression)
  • end
  • Check(FRbwParser.ExpressionCount gt 0, 'Error in
    counting expressions')
  • FRbwParser.ClearExpressions
  • Check(FRbwParser.ExpressionCount 0, 'Error in
    clearing expressions')
  • end

6
DUnit in Action
7
Manually Testing User Interaction
  • Manual
  • Ask the user to do something
  • Let the user decide if the results are correct
  • Problems
  • Slow
  • Unreliable
  • Discourages Testing

8
Automatically Test User Interaction
  • Simulate Mouse and Keyboard Events
  • Get Screen Captures of the Controls
  • Compare the New Screen Captures to Old Ones
  • Borlands private Zombie program does something
    similar. See http//www.stevetrefethen.com/files/
    index.html

9
Windows API for Simulating the Mouse and Keyboard
  • Mouse_Event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
  • Keybd_Event(key, MapvirtualKey(key, 0), flag, 0)

10
Simulate Mouse and Keyboard
  • // move the mouse to cell 0,1
  • APoint CellCenter(frmGridTest.TestGrid,
    0,1)
  • MoveMouseToPosition(APoint)
  • // double click on the cell to start
    editing text.
  • DoubleClick
  • // enter some text.
  • SimultateText('abcd efgh ijkl')

11
CellCenter
  • function CellCenter(Const Grid TCustomDrawGrid
    Const ACol, ARow integer) TPoint
  • var
  • ARect TRect
  • begin
  • ARect Grid.CellRect(ACol,ARow)
  • result.X (ARect.Left ARect.Right) div 2
  • result.Y (ARect.Top ARect.Bottom) div 2
  • result Grid.ClientToScreen(result)
  • end

12
MoveMouseToPosition
  • Procedure MoveMouseToPosition(Position TPoint)
  • Begin
  • Mouse.CursorPos Position
  • Application.ProcessMessages
  • end

13
MouseClick
  • procedure MouseGoesDown
  • begin
  • Mouse_Event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0,
    0)
  • end
  • procedure MouseGoesUp
  • begin
  • Mouse_Event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
  • end
  • procedure MouseClick
  • begin
  • MouseGoesDown
  • MouseGoesUp
  • end
  • procedure DoubleClick
  • begin
  • MouseClick
  • MouseClick
  • end

14
DragMouse
  • procedure DragMouse(Start, Stop TPoint)
  • Const
  • TenthSecond 100 // 100 milliseconds - 1/10
    second. This value works for me.
  • begin
  • MoveMouseToPosition(Start)
  • MouseGoesDown
  • try
  • MoveMouseToPosition(Stop)
  • // To generate a mouse move event, enough
    time must elapse.
  • // Empirically 1/20'th of a second is enough.
  • Sleep(TenthSecond)
  • Application.ProcessMessages
  • finally
  • MouseGoesUp
  • Application.ProcessMessages
  • end
  • end

15
SimultateText
  • Procedure SimultateText(const AString string)
  • var
  • CharIndex integer
  • AChar Char
  • KeyCode TKeyCode
  • Shift TShiftState
  • begin
  • for CharIndex 1 to Length(AString) do
  • begin
  • AChar AStringCharIndex
  • KeyCode.LongKeyCode VkKeyScan(AChar)
  • Shift
  • if (KeyCode.Shift and 1) ltgt 0 then
  • begin
  • Include(Shift, ssShift)
  • end
  • if (KeyCode.Shift and 2) ltgt 0 then
  • begin
  • Include(Shift, ssCtrl)
  • end
  • if (KeyCode.Shift and 4) ltgt 0 then
  • begin
  • Include(Shift, ssAlt)
  • end
  • PostKeyEx32(KeyCode.KeyCode, Shift, False)
  • end
  • end

16
PostKeyEx32
  • // from http//delphi.about.com/od/adptips2004/a/b
    ltip0604_4.htm
  • procedure PostKeyEx32(key Word const shift
    TShiftState specialkey Boolean)
  • type
  • TShiftKeyInfo record
  • shift Byte
  • vkey Byte
  • end
  • ByteSet set of 0..7
  • const
  • shiftkeys array 1..3 of TShiftKeyInfo
  • ((shift Ord(ssCtrl) vkey VK_CONTROL),
  • (shift Ord(ssShift) vkey VK_SHIFT),
  • (shift Ord(ssAlt) vkey VK_MENU))
  • var
  • flag DWORD
  • bShift ByteSet absolute shift
  • j Integer
  • begin
  • for j 1 to 3 do
  • begin
  • if shiftkeysj.shift in bShift then
  • keybd_event(shiftkeysj.vkey,
  • MapVirtualKey(shiftkeysj.vkey, 0), 0,
    0)
  • end
  • if specialkey then
  • flag KEYEVENTF_EXTENDEDKEY
  • else
  • flag 0
  • keybd_event(key, MapvirtualKey(key, 0), flag,
    0)
  • flag flag or KEYEVENTF_KEYUP
  • keybd_event(key, MapvirtualKey(key, 0), flag,
    0)
  • for j 3 downto 1 do
  • begin
  • if shiftkeysj.shift in bShift then

17
Comparing Appearances of Visual Components
  • PaintControlToBitMap(frmGridTest.TestGrid,
  • TestBitMap, True)
  • frmGridTest.Hide
  • BitmapKey
  • RbwDataGridAutoWordWrapAdjustRowHeight
  • UserPrompt
  • 'Has the text in the string and boolean
    cells word wrapped '
  • 'and have the rows expanded to
    accommodate the text?'
  • Result CompareAndUpdateBitmap(BitmapKey,
    UserPrompt,
  • TestBitMap)

18
PaintControlToBitMap
  • Procedure PaintControlToBitMap(Control TControl
  • BitMap TBitMap IncludeCursor boolean)
  • begin
  • // Set the size of the bitmap that will hold the
    image of Control
  • BitMap.Width Control.Width
  • BitMap.Height Control.Height
  • if Control is TWinControl then
  • begin
  • TWinControl(Control).PaintTo(BitMap.Canvas,
    0, 0)
  • end
  • else if Control is TGraphicControl then
  • begin
  • // Get a screen capture of the form
    containing the TGraphicControl
  • // and copy only the portion of that screen
    capture that contains
  • // the TGraphicControl into BitMap.

19
CompareAndUpdateBitmap
  • function CompareAndUpdateBitmap(const BitmapKey,
    UserPrompt string
  • TestBitMap TBitmap) Boolean
  • var
  • PredefinedBitMap TBitmap
  • begin
  • PredefinedBitMap FBitmapStorage.BitMapCollect
    ion.Find(BitmapKey)
  • result CompareBitMaps(TestBitMap,
    PredefinedBitMap)
  • if not result and (TestMethod tmScripted)
    then
  • begin
  • result UserCompareBitMap(PredefinedBitMap,
    TestBitMap, UserPrompt)
  • if result then
  • begin
  • if PredefinedBitMap nil then
  • begin
  • FBitmapStorage.
  • BitMapCollection.Store(BitmapKey,
  • TestBitMap)
  • end
  • else
  • begin
  • PredefinedBitMap.Assign(
  • TestBitMap)
  • end
  • end
  • end
  • end

20
Limitations
  • Someone has to check the appearance of a control
    manually at least once.
  • There can be no manual use of the mouse or
    keyboard during a test.
  • Changes to the computer outside of the control of
    the test, such as changing from small to large
    fonts, will affect the bitmap comparisons.

21
Summary
  • DUnit can be used to test visual controls.
  • Manual user interaction during tests can be
    reduced but not entirely eliminated.
  • The tests are fragile They are easily affected
    by changes to the computer outside the test.
Write a Comment
User Comments (0)
About PowerShow.com