Closed arosszay closed 8 years ago
That's just not how Python works :wink:
request.function
is the function object, and an attribute on it isn't the same thing as a local:
def fun():
x = 42
print(fun.x) # AttributeError
fun.x = 23
print(fun.x) # 23, nothing to do with `x` inside the function
Why do you need to do this?
I'm not sure I need to do this in order to accomplish what I want. Perhaps it's more accurate to ask why I want to do this? The reason why is because I have several test functions within a test class. For most of the tests, I want to begin the tests from a certain URL, however for a couple of the other ones I want to begin the test from a different URL. Additionally, I need to use different login credentials for the different tests because they are testing different things that I require different login credentials in order to test correctly.
I am trying to understand pytest as best I can in order to help me develop the best Selenium automation framework I can build! So because of this, I'm reading in the official pytest docs the following line:
Fixture function can accept the request object to introspect the “requesting” test function, class or module context.
Assuming I'm reading the truth, I went ahead and tried to utilize the ability of a fixture function to accept the request object to introspect the requesting test function. This didn't work, so that's why I'm asking the question.
I know I can introspect the requesting test module...this works on my machine. However, that convention does not make it easy to manage the specific urls and login credentials that need to be changed PER test within a single test module.
What do you think I should do? It would be really awesome if my test functions could communicate with the fixture functions to tell them what URL and login credentials to use when setting up the tests.
Here's the main fixture function I use to setup the tests:
@pytest.yield_fixture
def login_and_nav(request, navigate_to, login_with):
"""Fixture used to login and navigate to the page best suited for the test to begin conducting verifications."""
driver = Browser()
driver.maximize()
# Navigate to test url
driver.go_to_url(navigate_to)
# Login page will be displayed when user is not logged in, so we need to login at this step
login_page = LoginPage()
yield login_page.login(login_with)
print("Teardown fixture function is executed.")
if request.node.rep_call.failed:
print("Test FAILED. Name of test = {}. \n".format(request.node.nodeid))
driver.quit()
driver.__init__()
elif request.node.rep_call.passed:
print("Test PASSED. Name of test = {}. \n".format(request.node.nodeid))
`
NOTE: I'm really sorry, but I am having the most difficult and frustrating time figuring out how to correctly insert code in this text editor. I wish I could have it display for you all nice and everything, but I'm sorry I can't figure out how to do it as nice as you seem to have been able to do. Please pardon the lack of proper indentation throughout the entire stream of code inserts, hopefully you can still follow along and help!
First of all, are you aware of the existing plugins? There's pytest-selenium and pytest-splinter already :wink:
As for your issue, the usual thing to do is to use a marker like @pytest.mark.base_url('http://www.example.com/')
and then getting that via request.node.get_marker('base_url')
if I remember correctly.
To format code, you can use triple-backticks on their own line before/after the code. You can also simply select all lines and press the <>
button at the top right :wink:
@The-Compiler , no I was not aware of the existing plugins. Thank you for letting me know about them!
And for my issue, I mean, geez, you just solved it lickedy-split like that! Thank you very very much!!! Using the markers is an excellent solution to my problem! I knew what I was trying to do wasn't necessarily "needed" haha
You are the man. Thanks again! Also, since I am feeling quit good recently, I'd like to show you my appreciation for your help...similar to what I'm doing with nicco. It's the least I can do for you after you have already done so much for me!! Just hit me up with your paypal email and I'll make sure to let you know how much you've helped me. Cheers!!
Glad to hear that solves your issue! As nicoddemus said, that's much appreciated but of course by no means required :wink: My paypal mail is me@the-compiler.org.
I'm closing this then, as I assume you're all set.
Hello good people of pytest!
I have a major issue when trying to introspect the requesting test function from within a fixture. I am able to do the introspection successfully when doing it on the requesting test module, but NOT on the test function. I'd like for my fixture functions to be able to get data from my test functions.
Currently, I receive the following error:
> x = getattr(request.function, "url")
E AttributeError: 'function' object has no attribute 'url'
I've tried a couple things, like making the url variable in the test function to be nonlocal or global, using the concept of a closure(), ...all to no avail. I can't seem to understand how to make the fixture understand that yes, the 'function' object does indeed have an attribute 'url'.
I am using python 3.5.1 installed via the Anaconda 3 package on a Windows 10 machine. I run my code within Pycharm 2016.1.2 using pytest 2.9.1. I do not use a python virtual env.
Would a kind soul over here be able to help me with my situation? I seem to be stuck :/
Thanks!
Here's the fixture I wrote in a conftest.py file:
@pytest.fixture(scope="function")
def navigate_to(request):
"""Fixture used to determine the correct url to use when test execution starts"""
x = getattr(request.function, "url")
return x
Here's my test class including the test function I'm trying to make work _(NOTE: my fixture 'login_and_nav' takes in the 'navigateto' fixture above as a parameter):
@pytest.mark.usefixtures('login_and_nav')
class TestModuleNav(object):
"""Module Navigation Panel Selenium Tests."""