I am running selenium webdriver tests with nosetests. I want to capture a screenshot whenever nosetests fail. How can I do it in the most effective way, either by using webdriver, python or nosetests features?
-
1Similar, but for unittest: [How to execute code only on test failures with python unittest2?](http://stackoverflow.com/q/12290336/55075) at SO – kenorb May 16 '15 at 20:46
4 Answers
My solution
import sys, unittest
from datetime import datetime
class TestCase(unittest.TestCase):
def setUp(self):
some_code
def test_case(self):
blah-blah-blah
def tearDown(self):
if sys.exc_info()[0]: # Returns the info of exception being handled
fail_url = self.driver.current_url
print fail_url
now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S-%f')
self.driver.get_screenshot_as_file('/path/to/file/%s.png' % now) # my tests work in parallel, so I need uniqe file names
fail_screenshot_url = 'http://debugtool/screenshots/%s.png' % now
print fail_screenshot_url
self.driver.quit()

- 2,009
- 1
- 16
- 18
-
The question is about the `nose` framework, not the default `unittest`. – Alex Okrushko Feb 27 '13 at 20:15
-
-
I don't think that "python" implies "using another framework (like unittest)", however I might be wrong. – Alex Okrushko Feb 27 '13 at 20:58
-
Anyway, AFAIK in nose framework setUp and tearDown methods could be used to. I just showed the structure of test suit. – Furious Duck Feb 27 '13 at 23:06
-
3Nose will run tests written with the `unittest` package so there is no problem with this answer – Dan Passaro Apr 18 '13 at 20:14
-
Doesn't work, in my case sys.exc_info()[0] returns
and so it still takes screenshot as it is not None. Value of sys.exc_info() --> ( – Deep Dec 29 '14 at 08:34, Empty(), ) -
@Deep, the answer is old enough. I use py.test for my tests now and capturing screenshot on fail is a little bit more tricky here. Provide some info on your tests and I'll try to help you – Furious Duck Dec 29 '14 at 13:43
-
@Deep, let the necroposting begin! using sys.exc_info() is OS sensitive. The example provided works perfectly on Ubuntu, for example – Furious Duck Feb 21 '16 at 12:51
First of all, webdriver has the command:
driver.get_screenshot_as_file(screenshot_file_path)
I'm not an expert in nose (actually this is the first time I've looked into it), however I use py.test
framework (which is similar, however superior over nose
IMHO).
Mostly likely you'll have to create the "plugin" for nose where you'll have to implement the hook addFailure(test, err)
which is "Called when a test fails".
In this addFailure(test, err)
you can get the test name from Test object and generate the path for the file.
After that call driver.get_screenshot_as_file(screenshot_file_path)
.
In py.test
I create my plugin with implementation of def pytest_runtest_makereport(item, call):
hook. Inside I analyze call.excinfo
and create the screenshot if necessary.

- 7,212
- 6
- 44
- 63
-
I've tried this, but I can't get the instance of the TestCase in addFailure(). Could you share how that is possible (just by knowing the test name, which only points me to the appropriate class, not an instance) – vvondra Feb 05 '14 at 21:46
In Python you can use below code:
driver.save_screenshot('/file/screenshot.png')

- 155,785
- 88
- 678
- 743

- 936
- 2
- 16
- 29
Perhaps you have set up your tests differently, but in my experience you need to manually build in this type of functionality and repeat it at the point of failure. If you're performing selenium tests, chances are that like me, you're using a lot of find_element_by_something. I've written the following function to allow me to tackle this type of thing:
def findelement(self, selector, name, keys='', click=False):
if keys:
try:
self.driver.find_element_by_css_selector(selector).send_keys(keys)
except NoSuchElementException:
self.fail("Tried to send %s into element %s but did not find the element." % (keys, name))
elif click:
try:
self.driver.find_element_by_css_selector(selector).click()
except NoSuchElementException:
self.fail("Tried to click element %s but did not find it." % name)
else:
try:
self.driver.find_element_by_css_selector(selector)
except NoSuchElementException:
self.fail("Expected to find element %s but did not find it." % name)
In your case, the screenshot code (self.driver.get_screenshot_as_file(screenshot_file_path)) would go before the self.fail.
With this code, every time you want to interact with an element, you would call self.findelement('selector', 'element name')

- 355
- 1
- 5
- 17