16 from __future__
import print_function
21 if sys.platform.startswith(
'java'):
22 from java.awt
import Toolkit, Robot, Rectangle
23 from javax.imageio
import ImageIO
24 from java.io
import File
25 elif sys.platform ==
'cli':
27 clr.AddReference(
'System.Windows.Forms')
28 clr.AddReference(
'System.Drawing')
29 from System.Drawing
import Bitmap, Graphics, Imaging
30 from System.Windows.Forms
import Screen
41 from PIL
import ImageGrab
97 ROBOT_LIBRARY_SCOPE =
'TEST SUITE'
120 def __init__(self, screenshot_directory=None, screenshot_module=None):
127 return os.path.normpath(path.replace(
'/', os.sep))
130 _screenshot_dir = property
139 variables =
BuiltIn().get_variables()
140 outdir = variables[
'${OUTPUTDIR}']
141 log = variables[
'${LOGFILE}']
142 log = os.path.dirname(log)
if log !=
'NONE' else '.'
143 return self.
_norm_path_norm_path(os.path.join(outdir, log))
154 if not os.path.isdir(path):
155 raise RuntimeError(
"Directory '%s' does not exist." % path)
206 logger.debug(
'Using %s module/tool for taking screenshot.'
211 logger.warn(
'Taking screenshot failed: %s\n'
212 'Make sure tests are run with a physical or virtual '
218 if not os.path.exists(os.path.dirname(path)):
219 raise RuntimeError(
"Directory '%s' where to save the screenshot "
220 "does not exist" % os.path.dirname(path))
225 if basename.lower().endswith((
'.jpg',
'.jpeg')):
226 return os.path.join(directory, basename)
230 path = os.path.join(directory,
"%s_%d.jpg" % (basename, index))
231 if not os.path.exists(path):
236 logger.info(
'<a href="%s"><img src="%s" width="%s"></a>'
237 % (link, link, width), html=
True)
241 logger.info(
"Screenshot saved to '<a href=\"%s\">%s</a>'."
242 % (link, path), html=
True)
257 return self.
modulemodule !=
'no'
261 print(
"Cannot take screenshots.")
263 print(
"Using '%s' to take screenshot." % self.
modulemodule)
265 print(
"Not taking test screenshot.")
267 print(
"Taking test screenshot to '%s'." % path)
278 if sys.platform.startswith(
'java'):
280 if sys.platform ==
'cli':
282 if sys.platform ==
'darwin':
289 screenshot_takers = {
'wxpython': (wx, self.
_wx_screenshot_wx_screenshot),
293 if name
not in screenshot_takers:
294 raise RuntimeError(
"Invalid screenshot module or tool '%s'." % name)
295 supported, screenshot_taker = screenshot_takers[name]
297 raise RuntimeError(
"Screenshot module or tool '%s' not installed."
299 return screenshot_taker
302 for module, screenshot_taker
in [(wx, self.
_wx_screenshot_wx_screenshot),
308 return screenshot_taker
311 size = Toolkit.getDefaultToolkit().getScreenSize()
312 rectangle = Rectangle(0, 0, size.width, size.height)
313 image =
Robot().createScreenCapture(rectangle)
314 ImageIO.write(image,
'jpg', File(path))
317 bmp = Bitmap(Screen.PrimaryScreen.Bounds.Width,
318 Screen.PrimaryScreen.Bounds.Height)
319 graphics = Graphics.FromImage(bmp)
321 graphics.CopyFromScreen(0, 0, 0, 0, bmp.Size)
324 bmp.Save(path, Imaging.ImageFormat.Jpeg)
327 if self.
_call_call(
'screencapture',
'-t',
'jpg', path) != 0:
328 raise RuntimeError(
"Using 'screencapture' failed.")
332 return subprocess.call(command, stdout=subprocess.PIPE,
333 stderr=subprocess.STDOUT)
341 return os.sep ==
'/' and self.
_call_call(
'scrot',
'--version') == 0
344 if not path.endswith((
'.jpg',
'.jpeg')):
345 raise RuntimeError(
"Scrot requires extension to be '.jpg' or "
346 "'.jpeg', got '%s'." % os.path.splitext(path)[1])
347 if self.
_call_call(
'scrot',
'--silent', path) != 0:
348 raise RuntimeError(
"Using 'scrot' failed.")
353 context = wx.ScreenDC()
354 width, height = context.GetSize()
355 if wx.__version__ >=
'4':
356 bitmap = wx.Bitmap(width, height, -1)
358 bitmap = wx.EmptyBitmap(width, height, -1)
359 memory = wx.MemoryDC()
360 memory.SelectObject(bitmap)
361 memory.Blit(0, 0, width, height, context, -1, -1)
362 memory.SelectObject(wx.NullBitmap)
363 bitmap.SaveFile(path, wx.BITMAP_TYPE_JPEG)
366 window = gdk.get_default_root_window()
368 raise RuntimeError(
'Taking screenshot failed.')
369 width, height = window.get_size()
370 pb = gdk.Pixbuf(gdk.COLORSPACE_RGB,
False, 8, width, height)
371 pb = pb.get_from_drawable(window, window.get_colormap(),
372 0, 0, 0, 0, width, height)
374 raise RuntimeError(
'Taking screenshot failed.')
375 pb.save(path,
'jpeg')
378 ImageGrab.grab().save(path,
'JPEG')
381 raise RuntimeError(
'Taking screenshots is not supported on this platform '
382 'by default. See library documentation for details.')
385 if __name__ ==
"__main__":
386 if len(sys.argv)
not in [2, 3]:
387 sys.exit(
"Usage: %s <path>|test [wx|pygtk|pil|scrot]"
388 % os.path.basename(sys.argv[0]))
389 path = sys.argv[1]
if sys.argv[1] !=
'test' else None
390 module = sys.argv[2]
if len(sys.argv) > 2
else None
An always available standard library with often needed keywords.
def _get_named_screenshot_taker(self, name)
def _no_screenshot(self, path)
def _get_default_screenshot_taker(self)
def _get_screenshot_taker(self, module_name=None)
def _call(self, *command)
def _pil_screenshot(self, path)
def __init__(self, module_name=None)
def _scrot_screenshot(self, path)
def _gtk_screenshot(self, path)
def _java_screenshot(self, path)
def _wx_screenshot(self, path)
def _osx_screenshot(self, path)
def _cli_screenshot(self, path)
def test(self, path=None)
Test library for taking screenshots on the machine where tests are run.
def set_screenshot_directory(self, path)
Sets the directory where screenshots are saved.
def _save_screenshot(self, basename, directory=None)
def __init__(self, screenshot_directory=None, screenshot_module=None)
Configure where screenshots are saved.
def _screenshot_to_file(self, path)
def _get_screenshot_path(self, basename, directory)
def _validate_screenshot_path(self, path)
def _embed_screenshot(self, path, width)
def take_screenshot(self, name="screenshot", width="800px")
Takes a screenshot in JPEG format and embeds it into the log file.
def _screenshot_dir(self)
def _link_screenshot(self, path)
def take_screenshot_without_embedding(self, name="screenshot")
Takes a screenshot and links it from the log file.
def _norm_path(self, path)
def get_error_message()
Returns error message of the last occurred exception.
def abspath(path, case_normalize=False)
Replacement for os.path.abspath with some enhancements and bug fixes.
def get_link_path(target, base)
Returns a relative path to target from base.
def get_version(naked=False)