Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Semi-automated tests of Chrome with NVDA. | 6 """Semi-automated tests of Chrome with NVDA. |
| 7 | 7 |
| 8 This file performs (semi) automated tests of Chrome with NVDA | 8 This file performs (semi) automated tests of Chrome with NVDA |
| 9 (NonVisual Desktop Access), a popular open-source screen reader for | 9 (NonVisual Desktop Access), a popular open-source screen reader for |
| 10 visually impaired users on Windows. It works by launching Chrome in a | 10 visually impaired users on Windows. It works by launching Chrome in a |
| 11 subprocess, then launching NVDA in a special environment that simulates | 11 subprocess, then launching NVDA in a special environment that simulates |
| 12 speech rather than actually speaking, and ignores all events coming from | 12 speech rather than actually speaking, and ignores all events coming from |
| 13 processes other than a specific Chrome process ID. Each test automates | 13 processes other than a specific Chrome process ID. Each test automates |
| 14 Chrome with a series of actions and asserts that NVDA gives the expected | 14 Chrome with a series of actions and asserts that NVDA gives the expected |
| 15 feedback in response. | 15 feedback in response. |
| 16 | 16 |
| 17 The tests are "semi" automated in the sense that they are not intended to be | 17 The tests are "semi" automated in the sense that they are not intended to be |
| 18 run from any developer machine, or on a buildbot - it requires setting up the | 18 run from any developer machine, or on a buildbot - it requires setting up the |
| 19 environment according to the instructions in README.txt, then running the | 19 environment according to the instructions in README.txt, then running the |
| 20 test script, then filing bugs for any potential failures. If the environment | 20 test script, then filing bugs for any potential failures. If the environment |
| 21 is set up correctly, the actual tests should run automatically and unattended. | 21 is set up correctly, the actual tests should run automatically and unattended. |
| 22 """ | 22 """ |
| 23 | 23 |
| 24 | |
| 24 import os | 25 import os |
| 25 import pywinauto | |
| 26 import re | 26 import re |
| 27 import shutil | 27 import shutil |
| 28 import signal | 28 import signal |
| 29 import subprocess | 29 import subprocess |
| 30 import sys | 30 import sys |
| 31 import tempfile | 31 import tempfile |
| 32 import time | 32 import time |
| 33 import unittest | 33 import unittest |
| 34 import winapi | |
|
dmazzoni
2014/11/01 06:45:13
I can't find the winapi module. Did you mean win32
| |
| 34 | 35 |
| 35 CHROME_PROFILES_PATH = os.path.join(os.getcwd(), 'chrome_profiles') | 36 CHROME_PROFILES_PATH = os.path.join(os.getcwd(), 'chrome_profiles') |
| 36 CHROME_PATH = os.path.join(os.environ['USERPROFILE'], | 37 CHROME_PATH = os.path.join(os.environ['USERPROFILE'], |
| 37 'AppData', | 38 'AppData', |
| 38 'Local', | 39 'Local', |
| 39 'Google', | 40 'Google', |
| 40 'Chrome SxS', | 41 'Chrome SxS', |
| 41 'Application', | 42 'Application', |
| 42 'chrome.exe') | 43 'chrome.exe') |
| 43 NVDA_PATH = os.path.join(os.getcwd(), | 44 NVDA_PATH = os.path.join(os.getcwd(), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 NVDA_LOGPATH] | 99 NVDA_LOGPATH] |
| 99 self._nvda_proc = subprocess.Popen(args) | 100 self._nvda_proc = subprocess.Popen(args) |
| 100 self._nvda_proc.poll() | 101 self._nvda_proc.poll() |
| 101 if self._nvda_proc.returncode is None: | 102 if self._nvda_proc.returncode is None: |
| 102 print 'NVDA is running' | 103 print 'NVDA is running' |
| 103 else: | 104 else: |
| 104 print 'NVDA exited with code', self._nvda_proc.returncode | 105 print 'NVDA exited with code', self._nvda_proc.returncode |
| 105 sys.exit() | 106 sys.exit() |
| 106 print 'NVDA pid: %d' % self._nvda_proc.pid | 107 print 'NVDA pid: %d' % self._nvda_proc.pid |
| 107 | 108 |
| 108 app = pywinauto.application.Application() | 109 winapi.focusWindow(self._chrome_proc.pid) |
|
dmazzoni
2014/11/01 06:45:13
I can't find the focusWindow function in win32api,
| |
| 109 app.connect_(process = self._chrome_proc.pid) | |
| 110 self._pywinauto_window = app.top_window_() | |
| 111 | 110 |
| 112 try: | 111 try: |
| 113 self._WaitForSpeech(['Address and search bar edit', 'about:blank']) | 112 self._WaitForSpeech(['Address and search bar edit', 'about:blank']) |
| 114 except: | 113 except: |
| 115 self.tearDown() | 114 self.tearDown() |
| 116 | 115 |
| 117 def tearDown(self): | 116 def tearDown(self): |
| 118 print | 117 print |
| 119 print 'Shutting down' | 118 print 'Shutting down' |
| 120 | 119 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 print '"%s"' % line | 183 print '"%s"' % line |
| 185 raise Exception('Timed out') | 184 raise Exception('Timed out') |
| 186 time.sleep(0.1) | 185 time.sleep(0.1) |
| 187 | 186 |
| 188 # | 187 # |
| 189 # Tests | 188 # Tests |
| 190 # | 189 # |
| 191 | 190 |
| 192 def testTypingInOmnibox(self): | 191 def testTypingInOmnibox(self): |
| 193 # Ctrl+A: Select all. | 192 # Ctrl+A: Select all. |
| 194 self._pywinauto_window.TypeKeys('^A') | 193 winapi.typeKeys('{control}+a') |
| 195 self._WaitForSpeech('selecting about:blank') | 194 self._WaitForSpeech('selecting about:blank') |
| 196 | 195 |
| 197 # Type three characters. | 196 # Type three characters. |
| 198 self._pywinauto_window.TypeKeys('xyz') | 197 winapi.typeKeys('xyz') |
| 199 self._WaitForSpeech(['x', 'y', 'z']) | 198 self._WaitForSpeech(['x', 'y', 'z']) |
| 200 | 199 |
| 201 # Arrow back over two characters. | 200 # Arrow back over two characters. |
| 202 self._pywinauto_window.TypeKeys('{LEFT}') | 201 winapi.typeKeys('{left}') |
| 203 self._WaitForSpeech(['z', 'z', 'unselecting']) | 202 self._WaitForSpeech(['z', 'z', 'unselecting']) |
| 204 | 203 |
| 205 self._pywinauto_window.TypeKeys('{LEFT}') | 204 winapi.typeKeys('{left}') |
| 206 self._WaitForSpeech('y') | 205 self._WaitForSpeech('y') |
| 207 | 206 |
| 208 def testFocusToolbarButton(self): | 207 def testFocusToolbarButton(self): |
| 209 # Alt+Shift+T. | 208 # Alt+Shift+T. |
| 210 self._pywinauto_window.TypeKeys('%+T') | 209 winapi.typeKeys('{alt}+{shift}+t') |
| 211 self._WaitForSpeech('Reload button Reload this page') | 210 self._WaitForSpeech('Reload button Reload this page') |
| 212 | 211 |
| 213 def testReadAllOnPageLoad(self): | 212 def testReadAllOnPageLoad(self): |
| 214 # Ctrl+A: Select all | 213 # Ctrl+A: Select all |
| 215 self._pywinauto_window.TypeKeys('^A') | 214 winapi.typeKeys('{control}+a') |
| 216 self._WaitForSpeech('selecting about:blank') | 215 self._WaitForSpeech('selecting about:blank') |
| 217 | 216 |
| 218 # Load data url. | 217 # Load data url. |
| 219 self._pywinauto_window.TypeKeys('data:text/html,Hello<p>World.') | 218 winapi.typeKeys('data:text/html,Hello<p>World.') |
| 220 self._WaitForSpeech('dot') | 219 self._WaitForSpeech('dot') |
| 221 self._pywinauto_window.TypeKeys('{ENTER}') | 220 winapi.typeKeys('{enter}') |
| 222 self._WaitForSpeech( | 221 self._WaitForSpeech( |
| 223 ['document', | 222 ['document', |
| 224 'Hello', | 223 'Hello', |
| 225 'World.']) | 224 'World.']) |
| 226 | 225 |
| 226 def testNavigatingByWord(self): | |
| 227 winapi.typeKeys( | |
| 228 'data:text/html,<!DOCTYPE html><html><body>Word navigation</body></html> ') | |
|
dmazzoni
2014/11/01 06:45:13
You'll need an editable text field here for this t
| |
| 229 self._WaitForSpeech('greater') | |
| 230 winapi.typeKeys('{enter}') | |
| 231 self._WaitForSpeech( | |
| 232 ['document', | |
| 233 'Word navigation']) | |
| 234 winapi.typeKeys('{control}+{right}') | |
| 235 self._WaitForSpeech('navigation') | |
| 236 winapi.typeKeys('{control}+{left}') | |
| 237 self._WaitForSpeech('Word ') | |
| 238 | |
| 227 if __name__ == '__main__': | 239 if __name__ == '__main__': |
| 228 unittest.main() | 240 unittest.main() |
| 229 | 241 |
| OLD | NEW |