Comments (24)
Hello,
Well, there is no special here except using the selenium API to "capture a screenshot when a check fails or error occurs" (it totally depends on what you are doing in your tests) and then saving this screenshot using the attachment logging functions (see http://docs.lemoncheesecake.io/en/latest/logging.html#attachments).
Regards.
from lemoncheesecake.
okay, thank you for your answer. I was looking for something like: a global block of code which says that if a failure occurs at any step perform a 'capture screenshot'. So, Protractor offers something like this so I thought if lcc had it too from the setup or teardown methods in some way.
from lemoncheesecake.
Ok, I understand that you're looking for a kind of exception handler global to the test.
So no, there is no such things in lemoncheesecake, but you could implement something on your own using a context manager or a decorator for instance.
from lemoncheesecake.
okay, thanks for the pointer there. Let me know if you have a link to refer or I 'll try to figure it out if I can. Thanks. :)
from lemoncheesecake.
I think you will find plenty of online resources about context managers and decorators.
The idea is to use them to wrap your test, catch a given (selenium) exception, take a screenshot and save it.
from lemoncheesecake.
sure, will find that out. thanks for sharing the information. :)
from lemoncheesecake.
@anarang I just remembered the existence of the teardown_test
hook: http://docs.lemoncheesecake.io/en/latest/setup-and-teardown-suites.html.
It works this way:
@lcc.suite("MySuite")
class mysuite:
[...]
def teardown_test(self, test, status):
[...]
You won't be able to get the possible exception that has been raised within your test but you will be able to get the test's status (passed
or failed
) and to make and log a screenshot upon failure.
from lemoncheesecake.
thank you for the headsup here.I will give that a try and see if it works, but with this I think this will need to be included in every suite.
from lemoncheesecake.
If you are implementing suites as classes, you can:
- implement a base class that does the
teardown_test
- inherit this base class in your suite classes
from lemoncheesecake.
well, I am not implement suites as classes but using the SUITE variable to define a suite.
from lemoncheesecake.
Then, you can implement your teardown_test
function in some shared module and then simply import it in your various suite modules.
from lemoncheesecake.
Do you mean something like this:
suites/ - shared_test.py -> this will have only the test_teardown method
and then import shared_test.py in other modules at the same level.
from lemoncheesecake.
Not something in the "suites" directory because it will be interpreted as a suite, which is not.
And import the function itself (from something import test_teardown
), not the module itself, otherwise the test_teardown
won't be visible in the suite's module namespace.
from lemoncheesecake.
Hi @ndelon , thanks for the suggestion. The test_teardown is working as expected when imported, but it is unable to access the driver object and use the driver.get_screenshot_as_file. Below is a layout of how I use and initialise the webdriver object.
fixtures/fixture.py
@lcc.fixture(names=("driver", "driver_obj"), scope="session")
def setup():
lcc.log_info("Initialising the webdriver object, opening the browser...")
# Initialise the global webdriver, open the browser and maximise the
# browser window
driver = webdriver.Chrome(ChromeDriverManager(path=os.environ['PYTHONPATH']).install())
logging.info("Chrome driver has been initialised successfully")
driver.maximize_window()
driver.implicitly_wait(15)
driver.get(url)
# the global driver object can be used globally in the tests.
yield driver
driver.close()
driver.quit()
helpers/capture_screenshot.py
import lemoncheesecake.api as lcc
def teardown_test(test, status):
lcc.log_info(test.name)
lcc.log_info(status)
if status == "passed":
lcc.log_info("no failure")
else:
lcc.log_info("status was: failed")
driver.get_screenshot_as_file("s1.png")
lcc.log_info("saved screenshot")
lcc.save_attachment_file("s1.png")
suites/test1.py
from helpers.capture_screenshot import teardown_test
SUITE = {
"description": "Create a new test"
}
@lcc.test('test description')
--> the fixture "driver" is being called in every test in each suite to use the same driver object.
def create_test_test(driver):
#perform tests
check_that("test","a", equal_to("b"))
check_that("test", "a", equal_to("a"))
--> But the error I see: NameError: name 'driver' is not defined
I even tried :
def teardown_test(test, status, driver):
but that is unacceptable too.
The tear down test works correctly after each test in the suite but it is giving the error: name 'driver' is not defined. I tried it without the driver.screenshot and it worked well. Let me know if you didn't get my question.
I am unable to figure out how to use the fixture which initiates the driver object for this teardown_test.
Thanks, looking forward to your expert advice. :)
from lemoncheesecake.
Hello,
That's normal:
- you can't access a fixture from anywhere in the code
- the teardown function does not take fixtures argument
A solution would be to implement the suite as a class, like this:
# suites/test1.py
import lemoncheesecake.api as lcc
from lemoncheesecake.matching import *
@lcc.suite("Test 1")
class test1:
driver = lcc.inject_fixture()
@lcc.test('test description')
def create_test_test(self):
check_that("test","a", equal_to("b"))
check_that("test", "a", equal_to("a"))
# you can also do something with your driver using "self.driver"
def teardown_test(self, test, status):
lcc.log_info(test.name)
lcc.log_info(status)
if status == "passed":
lcc.log_info("no failure")
else:
lcc.log_info("status was: failed")
self.driver.get_screenshot_as_file("s1.png")
lcc.log_info("saved screenshot")
lcc.save_attachment_file("s1.png")
And of course, if every test suite follow the same pattern (having a "driver" fixture, having "teardown_test" method, etc...) you can extract it in a base class and inherit this base class in your actual test suites.
from lemoncheesecake.
Okay, so for the base class would it be something like this:
helpers/capture_screenshot.py:
import lemoncheesecake.api as lcc
class Screenshot:
driver = None
def teardown_test(self, test, status):
lcc.log_info(test.name)
lcc.log_info(status)
if status == "passed":
lcc.log_info("no failure")
else:
lcc.log_info("status was: failed")
self.driver.get_screenshot_as_file("s1.png")
lcc.log_info("saved screenshot")
lcc.save_attachment_file("s1.png")
And, then I make every suite into a class instead of a module and do this:
#suites/test1.py
from helpers.capture_screenshot import Screenshot
@lcc.suite("Create new product", rank="1")
class test_create_product(Screenshot):
driver = lcc.inject_fixture() ---> is the 'driver' here the name of the fixture? aren't we supposed to pass the name of the fixture here as lcc.inject_fixture("name_of_fixture"), it is working as expected ways.
@lcc.test('Verify that Warning is displayed when no product name is being entered')
def create_product_blank_name(self):
self.driver.get("url")
check_that("test","a", equal_to("b"))
check_that("test", "a", equal_to("a"))
driver=lcc.inject_fixture would be a part of every suite, correct?
from lemoncheesecake.
Simply do the driver = lcc.inject_fixture()
in your base test suite, not in the derived classes.
About lcc.inject_fixture()
: http://docs.lemoncheesecake.io/en/latest/api.html#lemoncheesecake.api.inject_fixture . So yes: if you don't specify an argument, it will lookup the fixture to inject from the assignment variable name.
from lemoncheesecake.
Base test suite as in suites/screenshot.py? I was keeping the above code in helpers/screenshot.py as itβs not a test suite.
from lemoncheesecake.
Yes, keep it in helpers/screenshot.py: it's not an actual test suite, it's just a base class.
from lemoncheesecake.
@ndelon thanks a lot for all the help. It worked for me. I would like to raise a PR for this in your docs for anyone to refer. Can you tell me what section would be the correct one in the docs to a PR to lemoncheesecake.
I am thinking of introducing something like:
How to capture screenshots using selenium + lemoncheesecake? or anything that you suggest. Let me know. thanks :)
from lemoncheesecake.
Thanks for wanting to help but this is far too much specific (selenium + the way you want to handle errors) to go to the standard documentation.
from lemoncheesecake.
okay, let me know if there is anything that I can contribute to. thanks for the help @ndelon :)
from lemoncheesecake.
Hello @anarang ,
FYI lemoncheesecake-selenium (https://lemoncheesecake-selenium.readthedocs.io/en/latest/) has just been released and should help you with some of the problematic you raised in this ticket.
Regards,
Nicolas.
from lemoncheesecake.
@ndelon ack, thanks for notifying.
from lemoncheesecake.
Related Issues (20)
- check_that vs. assert_that HOT 1
- lcc run skips execution of tests inside a folder created within the suites directory HOT 5
- Unable to view html reports when integrated with Jenkins HOT 2
- Is there a env variable that can fetch the name of the current test? HOT 4
- lcc run --exit-error-on-failure doesn't exit nonzero on failure in teardown_suite HOT 7
- setup_suite and teardown_suite still run when a suite is disabled HOT 3
- setup_test and teardown_test don't run when defined in outer class HOT 3
- rank=<int> doesn't seem to be working as expected, the test suites are not executing according to rank number. HOT 3
- common package HOT 3
- Unable to pass any parameters to teardown_suite HOT 3
- Getting "Connection pool is full, discarding connection: 127.0.0.1" error while running test cases on thread HOT 22
- error: "AttributeError: 'InjectedFixture' object has no attribute 'get'" HOT 19
- Is there any way to capture screenshot for fail test cases if my fixture is using scope as "session" and "per_thread=True"? HOT 12
- Having issue in Genrating xml, Junit Reports. Getting error `Unknown reporting backend`. HOT 2
- JUnit reporting not working with LCC HOT 2
- Allow wildcard in test dependencies HOT 7
- `lcc run` with reporting argument does not run tests HOT 4
- Getting issue while running lcc report --failed HOT 8
- Question: How to setup some steps to perform before any of the tests start to run and should be performed only once at the start. HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lemoncheesecake.