diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 96aab4e78..4f60b044b 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -308,7 +308,6 @@ class SeleniumLibrary(DynamicCore): def __init__(self, timeout=5.0, implicit_wait=0.0, run_on_failure='Capture Page Screenshot', screenshot_root_directory=None): - """SeleniumLibrary can be imported with several optional arguments. - ``timeout``: diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 2b97f4ab1..2d125a9f5 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -14,174 +14,108 @@ # See the License for the specific language governing permissions and # limitations under the License. -import errno import os -import re from robot.utils import get_link_path from SeleniumLibrary.base import LibraryComponent, keyword -from SeleniumLibrary.utils import events, is_falsy +from SeleniumLibrary.utils import is_noney class ScreenshotKeywords(LibraryComponent): - def __init__(self, ctx): - LibraryComponent.__init__(self, ctx) - self._screenshot_index = {} - self._screenshot_path_stack = [] - self.screenshot_root_directory = None - @keyword - def set_screenshot_directory(self, path, persist=False): - """Sets the root output directory for captured screenshots. - - ``path`` argument specifies the absolute path where the screenshots - should be written to. If the specified ``path`` does not exist, - it will be created. Setting ``persist`` specifies that the given - ``path`` should be used for the rest of the test execution, otherwise - the path will be restored at the end of the currently executing scope. + def set_screenshot_directory(self, path, persist='DEPRECATED'): + """Sets the directory for captured screenshots. + + ``path`` argument specifies the absolute path to a directory where + the screenshots should be written to. If the directory does not + exist, it will be created. The directory can also be set when + `importing` the library. If it is not configured anywhere, + screenshots are saved to the same directory where Robot Framework's + log file is written. + + ``persist`` argument is deprecated and has no effect. + + The previous value is returned and can be used to restore + the original value later if needed. + + Deprecating ``persist`` and returning the previous value are new + in SeleniumLibrary 3.0. """ - path = os.path.abspath(path) - self._create_directory(path) - if is_falsy(persist): - self._screenshot_path_stack.append(self.screenshot_root_directory) - # Restore after current scope ends - events.on('scope_end', 'current', - self._restore_screenshot_directory) - self.screenshot_root_directory = path + if is_noney(path): + path = None + else: + path = os.path.abspath(path) + self._create_directory(path) + if persist != 'DEPRECATED': + self.warn("'persist' argument to 'Set Screenshot Directory' " + "keyword is deprecated and has no effect.") + previous = self.ctx.screenshot_root_directory + self.ctx.screenshot_root_directory = path + return previous @keyword def capture_page_screenshot(self, filename='selenium-screenshot-{index}.png'): - """Takes a screenshot of the current page and embeds it into the log. + """Takes screenshot of the current page and embeds it into log file. ``filename`` argument specifies the name of the file to write the - screenshot into. If no ``filename`` is given, the screenshot is saved - into file _selenium-screenshot-{index}.png_ under the directory where - the Robot Framework log file is written into. The ``filename`` is - also considered relative to the same directory, if it is not - given in absolute format. If an absolute or relative path is given - but the path does not exist it will be created. - - Starting from SeleniumLibrary 1.8 if ``filename`` contains _{index}_ - characters, it will be automatically replaced with running index. - The running index is unique for each different filename. The absolute - path of the saved screenshot is always returned and it does not depend - does the ``filename`` contain _{index}_. See example 1 and 2 for more - details. - - The _{index}_ is replaced with the actual index by using Python's - [https://docs.python.org/2/library/stdtypes.html#str.format| - str.format] method, and it can be formatted using the standard - [https://docs.python.org/2/library/string.html#format-string-syntax| - format string syntax]. The example 3 shows this by setting the width and - the fill character. - - If there is a need to write literal _{index}_ or if ``filename`` - contains _{_ or _}_ characters, then the braces must be doubled. - - If _{index}_ is used, the computed filename will not overwrite - an existing file. The number chosen will be the first number - that results in a unique filename. For example, if the - computed name is screenshot-1.png but screenshot-1.png already - exists, screenshot-2.png will be tried, and so on, until a - unique name is found. - - Example 1: - | ${file1} = | Capture Page Screenshot | - | File Should Exist | ${OUTPUTDIR}${/}selenium-screenshot-1.png | - | Should Be Equal | ${file1} | ${OUTPUTDIR}${/}selenium-screenshot-1.png | - | ${file2} = | Capture Page Screenshot | - | File Should Exist | ${OUTPUTDIR}${/}selenium-screenshot-2.png | - | Should Be Equal | ${file2} | ${OUTPUTDIR}${/}selenium-screenshot-2.png | - - Example 2: - | ${file1} = | Capture Page Screenshot | ${OTHER_DIR}${/}other-{index}-name.png | - | ${file2} = | Capture Page Screenshot | ${OTHER_DIR}${/}some-other-name-{index}.png | - | ${file3} = | Capture Page Screenshot | ${OTHER_DIR}${/}other-{index}-name.png | - | File Should Exist | ${OTHER_DIR}${/}other-1-name.png | - | Should Be Equal | ${file1} | ${OTHER_DIR}${/}other-1-name.png | - | File Should Exist | ${OTHER_DIR}${/}some-other-name-1.png | - | Should Be Equal | ${file2} | ${OTHER_DIR}${/}some-other-name-1.png | - | File Should Exist | ${OTHER_DIR}${/}other-2-name.png | - | Should Be Equal | ${file3} | ${OTHER_DIR}${/}other-2-name.png | - - Example 3: - | Capture Page Screenshot | ${OTHER_DIR}${/}sc-{index:06}.png | - | File Should Exist | ${OTHER_DIR}${/}sc-000001.png | - + screenshot into. The directory where screenshots are saved can be + set when `importing` the library or by using the `Set Screenshot + Directory` keyword. If the directory is not configured, screenshots + are saved to the same directory where Robot Framework's log file is + written. + + Starting from SeleniumLibrary 1.8, if ``filename`` contains marker + ``{index}``, it will be automatically replaced with unique running + index preventing files to be overwritten. Indices start from 1, + and how they are represented can be customized using Python's + [https://docs.python.org/2/library/string.html#formatstrings| + format string syntax]. + + An absolute path to the created screenshot file is returned. + + Examples: + | `Capture Page Screenshot` | | + | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-1.png | + | ${path} = | `Capture Page Screenshot` | + | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-2.png | + | `File Should Exist` | ${path} | + | `Capture Page Screenshot` | custom_name.png | + | `File Should Exist` | ${OUTPUTDIR}/custom_name.png | + | `Capture Page Screenshot` | custom_with_index_{index}.png | + | `File Should Exist` | ${OUTPUTDIR}/custom_with_index_1.png | + | `Capture Page Screenshot` | formatted_index_{index:03}.png | + | `File Should Exist` | ${OUTPUTDIR}/formatted_index_001.png | """ - try: - self.browser - - except RuntimeError: - self.info("Couldn't capture page screenshot because no browser is opened") - - else: - path, link = self._get_screenshot_paths(filename) - self._create_directory(path) - if hasattr(self.browser, 'get_screenshot_as_file'): - if not self.browser.get_screenshot_as_file(path): - raise RuntimeError('Failed to save screenshot ' + link) - else: - if not self.browser.save_screenshot(path): - raise RuntimeError('Failed to save screenshot ' + link) - # Image is shown on its own row and thus prev row is closed on purpose - msg = ( - '
+ [Documentation]
+ ... LOG 2:3
+ ... LOG 8:3
[Setup] Remove Files ${OUTPUTDIR}/selenium-screenshot-*.png
${file} = Capture Page Screenshot
${count} = Count Files In Directory ${OUTPUTDIR} selenium-screenshot-*.png
@@ -19,70 +21,66 @@ Capture page screenshot to default location
Should Be Equal As Integers ${count} 2
Capture page screenshot to custom file
- [Documentation] Capture page screenshot to custom file
[Setup] Remove Files ${OUTPUTDIR}/custom-screenshot.png
Capture Page Screenshot custom-screenshot.png
File Should Exist ${OUTPUTDIR}/custom-screenshot.png
Capture page screenshot to custom directory
- [Documentation] Capture page screenshot to custom directory
[Setup] Remove Files ${TEMPDIR}/seleniumlibrary-screenshot-test.png
Capture Page Screenshot ${TEMPDIR}/seleniumlibrary-screenshot-test.png
File Should Exist ${TEMPDIR}/seleniumlibrary-screenshot-test.png
Capture page screenshot to non-existing directory
- [Documentation] Capture page screenshot to non-existing directory
[Setup] Remove Directory ${OUTPUTDIR}/screenshot recursive
Capture Page Screenshot screenshot/test-screenshot.png
File Should Exist ${OUTPUTDIR}/screenshot/test-screenshot.png
-Capture page screenshot to custom root directory
- [Documentation] Capture page screenshot to custom root directory
+Set Screenshot Directory
[Setup] Remove Directory ${OUTPUTDIR}/custom-root recursive
- Set Screenshot Directory ${OUTPUTDIR}/custom-root
+ ${previous} = Set Screenshot Directory ${OUTPUTDIR}/custom-root
${file} = Capture Page Screenshot custom-root-screenshot.png
File Should Exist ${OUTPUTDIR}/custom-root/custom-root-screenshot.png
Should Be Equal ${file} ${OUTPUTDIR}${/}custom-root${/}custom-root-screenshot.png
+ [Teardown] Set Screenshot Directory ${previous}
-Ensure screenshot captures revert to default root directory
- [Documentation] Ensure screenshot captures revert to default root directory
+Set Screenshot Directory set back to previous value
+ [Documentation] The directory is actually set already by previous test.
[Setup] Remove Files ${OUTPUTDIR}/default-root-screenshot.png
Capture Page Screenshot default-root-screenshot.png
File Should Exist ${OUTPUTDIR}/default-root-screenshot.png
Capture page screenshot with unique index
- [Setup] Remove Directory ${OUTPUTDIR}${/}screenshot-and-index recursive
- ${file1} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}other-{index}-name.png
- ${file2} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}some-other-name-{index}.png
- ${file3} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}other-{index}-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}other-1-name.png
+ [Setup] Remove Directory ${OUTPUTDIR}/screenshot-and-index recursive
+ ${file1} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/other-{index}-name.png
+ ${file2} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/some-other-name-{index}.png
+ ${file3} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/other-{index}-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/other-1-name.png
Should Be Equal ${file1} ${OUTPUTDIR}${/}screenshot-and-index${/}other-1-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}some-other-name-1.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/some-other-name-1.png
Should Be Equal ${file2} ${OUTPUTDIR}${/}screenshot-and-index${/}some-other-name-1.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}other-2-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/other-2-name.png
Should Be Equal ${file3} ${OUTPUTDIR}${/}screenshot-and-index${/}other-2-name.png
Capturing a page screenshot with two indexes should not cause an error
- ${file} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}two-{index}-in-{index}-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}two-1-in-1-name.png
+ ${file} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/two-{index}-in-{index}-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/two-1-in-1-name.png
Should Be Equal ${file} ${OUTPUTDIR}${/}screenshot-and-index${/}two-1-in-1-name.png
Capture page screenshot with index formatting
- Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}format-{index:06}-name.png
- Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}format-{index:06}-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}format-000001-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}format-000002-name.png
+ Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/format-{index:06}-name.png
+ Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/format-{index:06}-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/format-000001-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/format-000002-name.png
Capture page screenshot with escaped braces
- ${file} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}brackets-{{index}}-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}brackets-{index}-name.png
+ ${file} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/brackets-{{index}}-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/brackets-{index}-name.png
Should Be Equal ${file} ${OUTPUTDIR}${/}screenshot-and-index${/}brackets-{index}-name.png
- ${file} = Capture Page Screenshot ${OUTPUTDIR}${/}screenshot-and-index${/}brackets-{{index-name.png
- File Should Exist ${OUTPUTDIR}${/}screenshot-and-index${/}brackets-{index-name.png
+ ${file} = Capture Page Screenshot ${OUTPUTDIR}/screenshot-and-index/brackets-{{index-name.png
+ File Should Exist ${OUTPUTDIR}/screenshot-and-index/brackets-{index-name.png
Capture page screenshot computed name is unique
- [Documentation] verify that computed filenames are unique
- [Setup] run keywords
+ [Setup] Run Keywords
... Remove files ${OUTPUTDIR}/unique-screenshot-*.png
... AND Touch ${OUTPUTDIR}/unique-screenshot-1.png
... AND Touch ${OUTPUTDIR}/unique-screenshot-2.png
@@ -102,8 +100,7 @@ Capture page screenshot computed name is unique
File Should Exist ${expected}
Capture page screenshot advanced formatting name is unique
- [Documentation] verify that computed filenames are unique
- [Setup] run keywords
+ [Setup] Run Keywords
... Remove files ${OUTPUTDIR}/advanced-screenshot-*.png
... AND Touch ${OUTPUTDIR}/advanced-screenshot-002.png
... AND Touch ${OUTPUTDIR}/advanced-screenshot-003.png
@@ -123,8 +120,7 @@ Capture page screenshot advanced formatting name is unique
File Should Exist ${expected}
Capture page screenshot explicit name will overwrite
- [Documentation] Verify that existing filenames get overwritten if explicitly named
- [Setup] run keywords
+ [Setup] Run Keywords
... Remove files ${OUTPUTDIR}/explicit-screenshot-*.png
... AND Touch ${OUTPUTDIR}/explicit-screenshot-1.png
# make sure we are starting out with a single file in the output directory
@@ -140,7 +136,19 @@ Capture page screenshot explicit name will overwrite
File Should Exist ${OUTPUTDIR}/explicit-screenshot-1.png
Capture page screenshot with closed browser
- [Documentation] LOG 2:1 Couldn't capture page screenshot because no browser is opened
+ [Documentation] LOG 2:1 Cannot capture screenshot because no browser is open.
[Setup] Close All Browsers
Capture Page Screenshot
[Teardown] Open Browser To Start Page
+
+Set screenshot directory when importing
+ [Setup] Remove Files ${TEMPDIR}/selenium-screenshot-*.png
+ Import Library SeleniumLibrary screenshot_root_directory=${TEMPDIR} WITH NAME SL2
+ Set Library Search Order SL2
+ Open Browser To Start Page
+ Capture Page Screenshot
+ File Should Exist ${TEMPDIR}/selenium-screenshot-1.png
+ Set Screenshot Directory ${OUTPUTDIR}/screenshots
+ Capture Page Screenshot custom-name-{index}.png
+ File Should Exist ${OUTPUTDIR}/screenshots/custom-name-1.png
+ [Teardown] Close Browser
diff --git a/test/unit/keywords/test_keyword_arguments_screenshot.py b/test/unit/keywords/test_keyword_arguments_screenshot.py
deleted file mode 100644
index 75a72afd8..000000000
--- a/test/unit/keywords/test_keyword_arguments_screenshot.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import unittest
-
-from mockito import mock, unstub, when, verify
-from mockito.matchers import ANY
-
-from SeleniumLibrary.keywords import ScreenshotKeywords
-from SeleniumLibrary.utils import events
-
-
-class KeywordArgumentsElementTest(unittest.TestCase):
-
- def setUp(self):
- ctx = mock()
- ctx._browser = mock()
- self.screen = ScreenshotKeywords(ctx)
- self.ctx = ctx
-
- def tearDown(self):
- unstub()
-
- def test_set_screenshot_directory(self):
- when(events).on(ANY, ANY, ANY)
- self.screen.set_screenshot_directory('/foo')
- self.screen.set_screenshot_directory('/foo', None)
- self.screen.set_screenshot_directory('/foo', 'None')
- self.screen.set_screenshot_directory('/foo', 'False')
- verify(events, times=4).on(ANY, ANY, ANY)
- self.screen.set_screenshot_directory('/foo', True)
- self.screen.set_screenshot_directory('/foo', 'True')
- self.screen.set_screenshot_directory('/foo', 'Yes')
- verify(events, times=4).on(ANY, ANY, ANY)