This is the article on the 5th day of Selenium / Appium Advent Calendar 2014. The day before was hiroshitoda-prospire's "Environmental configuration management for running Selenium".
Hello. My name is myhr and I am a test engineer. Today I would like to introduce a patch for taking full size screenshots in Chrome. I think that it has already been introduced in other articles, but this time I would like to explain in detail for beginners.
For the background, see last year's article by hiroshitoda-prospire "Tips for taking screenshots with Selenium WebDriver I was allowed to refer to.
I also took screenshots in Firefox and Chrome.
--For vertically long pages
--For horizontally long pages
Firefox is able to capture the end of the page, but Chrome only shows what you can see on the browser screen. Therefore, unlike Firefox, you can see that every time you take a screenshot, you bother to bring the browser you are operating to the front.
RemoteWebDriver Modes The remote webdriver comes in two flavours:
- Client mode: where the language bindings connect to the remote instance. This is the way that the FirefoxDriver, OperaDriver and the RemoteWebDriver client normally work.
- Server mode: where the language bindings are responsible for setting up the server, which the driver running in the browser can connect to. The ChromeDriver works in this way.
I think that the reason why the behavior is different only for Chrome Driver is probably related to this area, but I would appreciate it if you could tell me more about it.
env | version |
---|---|
Python | 3.4.2 |
Pillow ※ | 2.4.0 |
selenium | 2.44.0 |
ChromeDriver | 2.9.248307 |
Chrome | 39.0.2171.71 (64-bit) |
pip instsall Pillow
The method is simple. I will do it in a forcible and muddy way.
var | description | var | description |
---|---|---|---|
view_width ※ | Horizontal size of browser | stitched_image | Image that becomes a screenshot |
view_height ※ | Vertical size of the browser | tmp_image | Image that will be part of the screenshot |
total_width ※ | Horizontal size of page | row_count | Number of times to scroll vertically |
total_height ※ | Vertical size of page | col_count | Number of scrolls horizontally |
scroll_width | Scrolled horizontal size meter | new_width | The remaining horizontal size of the page |
scroll_height | Scrolled vertical size total | new_height | The remaining vertical size of the page |
※ Fixed value
scroll_width, scroll_height, row_count, col_count = 0
. tmp_ {row_count} _ {col_count} .png
, it will be easier to understand when you look at the file later. scroll_height + = view_height; row_count ++; scroll_width, col_count = 0
https://gist.github.com/yui3880/a63ced61806d8517c4a3
from PIL import Image
import time
def save_screenshot(self, filename, fullsize=False):
filepath = '/'.join(filename.split('/')[:-1])
if fullsize:
#Scroll to the top left of the page
self.execute_script("window.scrollTo(0, 0);")
#Get page size
total_height = self.execute_script("return document.body.scrollHeight")
total_width = self.execute_script("return document.body.scrollWidth")
#Get screen size
view_width = self.execute_script("return window.innerWidth")
view_height = self.execute_script("return window.innerHeight")
#For image processing
stitched_image = Image.new("RGB", (total_width, total_height))
#For scroll operation
scroll_width = 0
scroll_height = 0
row_count = 0
#Vertical scrolling §
while scroll_height < total_height:
#Side-scroll initialization
col_count = 0
scroll_width = 0
self.execute_script("window.scrollTo(%d, %d)" % (scroll_width, scroll_height))
#Side-scrolling process
while scroll_width < total_width:
if col_count > 0:
#Side-scrolling for screen size
self.execute_script("window.scrollBy("+str(view_width)+",0)")
tmpname = filepath + '/tmp_%d_%d.png' % (row_count, col_count)
self.get_screenshot_as_file(tmpname)
time.sleep(3)
#When you reach the right or bottom edge, cut the image and stitched_Paste to image
if scroll_width + view_width >= total_width or scroll_height + view_height >= total_height:
new_width = view_width
new_height= view_height
if scroll_width + view_width >= total_width:
new_width = total_width - scroll_width
if scroll_height + view_height >= total_height:
new_height = total_height - scroll_height
tmp_image = Image.open(tmpname)
tmp_image.crop((view_width - new_width, view_height - new_height, view_width, view_height)).save(tmpname)
stitched_image.paste(Image.open(tmpname), (scroll_width, scroll_height))
scroll_width += new_width
#Paste normally
else:
stitched_image.paste(Image.open(tmpname), (scroll_width, scroll_height))
scroll_width += view_width
col_count += 1
scroll_height += view_height
time.sleep(3)
#Stitched to the specified filename_image storage
stitched_image.save(filename)
return True
# fullsize=If False, take a normal screenshot
else:
self.get_screenshot_as_file(filename)
Let's hit the language binding directly.
--For python: {$ PYTHONPATH} /site-packages/webdriver/chrome/webdriver.py
...
from selenium.common.exceptions import WebDriverException
from .service import Service
from .options import Options
+ from PIL import Image
+ import time
class WebDriver(RemoteWebDriver):
...
+ def save_screenshot(self, filename, fullsize=False):
+ #Get page size
+ total_width = self.execute_script("return document.body.scrollWidth")
+ total_height = self.execute_script("return document.body.scrollHeight")
...
――Advantage: If you put it in, all Chrome screenshots will be taken in this way, and the calling method is the same as before --Disadvantage: It is necessary to apply a patch every time the version of selenium is changed. It may not work depending on the environment.
Change self to webdriver or something in the method in your screenshot.
Next is nkns165. Thank you.