pyWinAuto: c:\.projects\py_pywinauto\pywinauto\tests\overlapping.py

0001# GUI Application automation and testing library
0002# Copyright (C) 2006 Mark Mc Mahon
0003#
0004# This library is free software; you can redistribute it and/or
0005# modify it under the terms of the GNU Lesser General Public License
0006# as published by the Free Software Foundation; either version 2.1
0007# of the License, or (at your option) any later version.
0008#
0009# This library is distributed in the hope that it will be useful,
0010# but WITHOUT ANY WARRANTY; without even the implied warranty of
0011# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0012# See the GNU Lesser General Public License for more details.
0013#
0014# You should have received a copy of the GNU Lesser General Public
0015# License along with this library; if not, write to the
0016#    Free Software Foundation, Inc.,
0017#    59 Temple Place,
0018#    Suite 330,
0019#    Boston, MA 02111-1307 USA
0020"""Overlapping Test
0021
0022**What is checked**
0023The overlapping test checks for controls that occupy the same space as some
0024other control in the dialog.
0025
0026  + If the reference controls are available check for each pair of controls:
0027
0028    - If controls are exactly the same size and position in reference then
0029      make sure that they are also in the localised.
0030    - If a reference control is wholly contained in another make sure that the
0031      same happens for the controls being tested.
0032
0033  + If the reference controls are not available only the following check can
0034    be done
0035
0036    - If controls are overlapped in localised report a bug (if reference is
0037      available it is used just to say if this overlapping happens in reference
0038      also)
0039
0040
0041**How is it checked**
0042Various tests are performed on each pair of controls to see if any of the
0043above conditions are met. The most specific tests that can be performed are
0044done 1st so that the bugs reported are as specific as possible. I.e. we report
0045that 2 controls are not exactly overlapped when they should be rather than jut
0046reporting that they are overlapped which contains less information.
0047
0048**When is a bug reported**
0049A bug is reported when:
0050
0051    - controls are overlapped (but not contained wholly, and not exactly
0052      overlapped)
0053    - reference controls are exactly overlapped but they are not in tested
0054      dialog
0055    - one reference control is wholly contained in another but not in
0056      tested dialog
0057
0058
0059**Bug Extra Information**
0060This test produces 3 different types of bug:
0061BugType: "Overlapping"
0062Name    Description
0063OverlappedRect  <What this info is>, Rectangle
0064
0065**BugType -  "NotContainedOverlap"**
0066There is no extra information associated with this bug type
0067
0068**BugType - "NotExactOverlap"**
0069There is no extra information associated with this bug type
0070
0071**Is Reference dialog needed**
0072For checking whether controls should be exactly overlapped and whether they
0073should be wholly contained the reference controls are necessary. If the
0074reference controls are not available then only simple overlapping of controls
0075will be checked.
0076
0077**False positive bug reports**
0078If there are controls in the dialog that are not visible or are moved
0079dynamically it may cause bugs to be reported that do not need to be logged.
0080If necessary filter out bugs with hidden controls.
0081
0082**Test Identifier**
0083The identifier for this test is "Overlapping"
0084"""
0085
0086testname = "Overlapping"
0087__revision__ = "$Revision: 545 $"
0088
0089from pywinauto import win32structures
0090
0091#====================================================================
0092def OverlappingTest(windows):
0093    "Return the repeated hotkey errors"
0094
0095    bugs = []
0096
0097    for i, first in enumerate(windows[:-1]):
0098        first_rect = first.Rectangle()
0099
0100        if first.ref:
0101            first_ref_rect = first.ref.Rectangle()
0102
0103        for second in windows[i+1:]:
0104            second_rect = second.Rectangle()
0105
0106
0107            # if the reference controls are available
0108            if first.ref and second.ref:
0109                second_ref_rect = second.ref.Rectangle()
0110
0111                if first_ref_rect == second_ref_rect and                       not first_rect == second_rect:
0113
0114                    bugs.append(([first, second], {}, "NotExactOverlap", 0))
0115
0116                elif _ContainedInOther(first_ref_rect,second_ref_rect) and                       not _ContainedInOther(first_rect, second_rect):
0118
0119                    bugs.append(
0120                        ([first, second], {}, "NotContainedOverlap", 0))
0121
0122
0123            if _Overlapped(first_rect, second_rect) and                   not _ContainedInOther(first_rect, second_rect) and                   not first_rect == second_rect:
0126
0127                ovlRect = _OverlapRect(first_rect, second_rect)
0128
0129                isInRef = -1
0130                if first.ref and second.ref:
0131                    isInRef = 0
0132                    if _Overlapped(first_ref_rect, second_ref_rect):
0133                        isInRef = 1
0134
0135                bugs.append((
0136                    [first, second],
0137                    {"OverlappedRect":ovlRect},
0138                    testname,
0139                    isInRef))
0140
0141    return bugs
0142
0143
0144
0145#====================================================================
0146def _ContainedInOther(rect1, rect2):
0147    "Return true if one rectangle completely contains the other"
0148    # check if rect2 is inside rect1
0149
0150    if rect1.left   >= rect2.left and           rect1.top    >= rect2.top and           rect1.right  <= rect2.right and           rect1.bottom <= rect2.bottom:
0154        return True
0155
0156    # check if rect1 is inside rect2
0157    elif rect2.left  >= rect1.left and           rect2.top    >= rect1.top and           rect2.right  <= rect1.right and           rect2.bottom <= rect1.bottom:
0161        return True
0162
0163    # no previous return - so must not be included
0164    return False
0165
0166
0167def _Overlapped(rect1, rect2):
0168    "Return true if the two rectangles are overlapped"
0169    ovlRect = _OverlapRect(rect1, rect2)
0170
0171    # if it is actually a bug
0172    if ovlRect.left < ovlRect.right and ovlRect.top < ovlRect.bottom:
0173        # make sure that the rectangle is the 'right way around :-)'
0174        return True
0175    return False
0176
0177
0178# Case 1: L2 between L1 and R1 -> max(L1, L2) < min(R1, R2)
0179#
0180# L1            R1
0181# ---------------
0182#        L2          R2
0183#        --------------
0184#
0185# Case 2: R2 outside L1 and R1 -> NOT max(L1, L2) < min(R1, R2)
0186#
0187#               L1          R1
0188#               -------------
0189# L2        R2
0190# ------------
0191#
0192
0193class OptRect(object): pass
0194
0195def _OverlapRect (rect1, rect2):
0196    "check whether the 2 rectangles are actually overlapped"
0197
0198    ovlRect = OptRect()#win32structures.RECT()
0199
0200    ovlRect.left   = max(rect1.left,   rect2.left)
0201    ovlRect.right  = min(rect1.right,  rect2.right)
0202    ovlRect.top    = max(rect1.top,    rect2.top)
0203    ovlRect.bottom = min(rect1.bottom, rect2.bottom)
0204
0205    return ovlRect