I have the next file with tests
import pytest
from httpx import AsyncClient
import sys
import config
from main import app
#pytest.mark.asyncio
async def test_register():
async with AsyncClient(app=app, base_url="http://test") as ac:
response = await ac.post("/register", )
assert response.status_code == 200
I want to run it like
if __name__ == '__main__':
pytest.run() # Or something alike
How I can do it? I need it to assign name 'main' to this module, because the main module (which import above) has a constraint like: if __name__ == '__main__', so without it tests will not be run indeed.
pytest.main() would run pytest in the current working directory and this would include your file depending on the filename (e.g. if the filename starts with test_). To run pytest on the current file only you can run:
if __name__ == "__main__":
pytest.main([__file__])
Related
There are 2 files, the code in the first one is:
import pytest
class TestXdist2():
#pytest.mark.dependency(name="aa")
def test_t1(self):
print("\ntest_1")
assert True
the code in the second file is:
import pytest
import sys, os
sys.path.append(os.getcwd())
from testcases.test_xdist_2 import TestXdist2
class TestXdist1():
def setup_class(self):
self.x = TestXdist2()
#pytest.mark.dependency(depends=["aa"], scope="module")
def test_t2(self):
print("\ntest_t2")
assert 1==1
if __name__ == "__main__":
pytest.main(["-s", "-v", f"{os.path.abspath('testcases')}/test_xdist_1.py"])
when I run the senond file, I thought test case "test_t1" should be ran firstly, then "test_t2" ran secondly, but the result is like this, "test_t2" is skipped, I don'y know why,
PS D:\gitProjects\selenium_pytest_demo> & D:/Python38/python.exe d:/gitProjects/selenium_pytest_demo/testcases/test_xdist_1.py
Test session starts (platform: win32, Python 3.8.7, pytest 6.2.2, pytest-sugar 0.9.4)
cachedir: .pytest_cache
metadata: {'Python': '3.8.7rc1', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '6.2.2', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'allure-pytest': '2.8.35', 'dependency': '0.5.1', 'forked': '1.3.0', 'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'sugar': '0.9.4', 'xdist': '2.2.1'}, 'JAVA_HOME': 'D:\\Java\\jdk-15.0.1'}
rootdir: D:\gitProjects\selenium_pytest_demo, configfile: pytest.ini
plugins: allure-pytest-2.8.35, dependency-0.5.1, forked-1.3.0, html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, sugar-0.9.4, xdist-2.2.1
collecting ...
testcases\test_xdist_1.py::TestXdist1.test_t2 s 50% █████
test_1
testcases\test_xdist_2.py::TestXdist2.test_t1 ✓ 100% ██████████
Results (0.04s):
1 passed
1 skipped
This is the expected behavior - pytest-dependency does not order testcases, it only skips testcases if the testcase they depend on is skipped or failed. There exists a PR that would change that, but is not merged
Until that, you can use pytest-order. If you just want the ordering, you can use relative markers. If you also want to skip tests if the test they depend on failed, you can use pytest-dependency as before, but use the pytest-order option --order-dependencies to order the tests additionally.
Disclaimer:
I'm the author of pytest-order (which is a fork of pytest-ordering).
I'm using Pytest to test connection to database which hangs
when I run it:
def test_db():
db.create_all()
new_comment = Comments(comment='python rocks')
db.session.add(new_comment)
db.session.commit()
entry = Comments.query.all()
assert len(entry) == 1
db.drop_all()
The table is created successfully but I can't run select * from Comments; as it hangs too. I have to kill both windows.
How can I fix this ?
This code did the trick:
from sqlalchemy.engine.reflection import Inspector
from sqlalchemy import create_engine
engine = create_engine('mysql://user:password#localhost/table')
inspector = Inspector.from_engine(engine)
def test_db():
db.create_all()
assert inspector.get_table_names()[0] == 'comments'
db.drop_all()
I'm trying to write a program that automatically sets up python shell scripts for me. Heres the code:
#!/usr/bin/env python3
import click
import subprocess
#click.command()
#click.argument('name')
def foo(name):
subprocess.call("cd ~/bin", shell=True)
subprocess.call(["touch", name])
subprocess.call(["echo", "'#!/usr/bin/env python3'", ">>", name])
subprocess.call(["chmod", "+x", name])
if __name__ == '__main__':
foo()
When it runs this is the output I get:
'#!/usr/bin/env python3' >> foo
A better way to approach this problem is to use the built-in Python libraries for creating files so that you can catch the exceptions easier. I've made a simple outline for you, but you should add some error checking.
import click
import os
import stat
#click.command()
#click.argument('name')
def foo(name):
file_to_create = os.path.expanduser("~/bin/") + name
with open(file_to_create, 'w') as file:
file.write("#!/usr/bin/env python3\n")
file_stats = os.stat(file_to_create)
os.chmod(file_to_create, file_stats.st_mode | stat.S_IEXEC) # equivalent of 'chmod +x'
if __name__ == '__main__':
foo()
I have a pytest testing project running selenium tests that has a structure like:
ProjRoot
|
|_Pytest.ini
|_____________TestFolderA
| |
| |_test_folderA_tests1.py
| |_test_folderA_tests2.py
|
|____________TestFolderB
| |
| |_test_folderB_test1.py
| |_test_folderA_tests2.py
|
|
|___________TestHelperModules
| |
| |_VariousTestHelperModules
|
|____________DriversAndTools
|___(contains chromedriver.exe, firefox profile folder etc)
I have a confTest.py file which I currently run in the ProjRoot, which I use as a setup and tear down for establishing the browser session for each test that is run. It runs each test twice. Once for Chrome and once for Firefox. In my tests I just utilise the resulting driver fixture. The conftest file is as below:
#conftest.py
import pytest
import os
import rootdir_ref
from selenium.webdriver.common.keys import Keys
import time
from webdriverwrapper.pytest import *
from webdriverwrapper import Chrome
from webdriverwrapper import DesiredCapabilities
from webdriverwrapper import Firefox
from webdriverwrapper import FirefoxProfile
#when running tests from command line we should be able to pass --url=www..... for a different website, check what order these definitions need to be in
def pytest_addoption(parser):
parser.addoption('--url', default='https://test1.testsite.com.au')
#pytest.fixture(scope='function')
def url(request):
return request.config.option.url
browsers = {
'firefox': Firefox,
'chrome': Chrome,
}
#pytest.fixture(scope='function',
params=browsers.keys())
def browser(request):
if request.param == 'firefox':
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
firefox_capabilities['handleAlerts'] = True
theRootDir = os.path.dirname(rootdir_ref.__file__)
ffProfilePath = os.path.join(theRootDir, 'DriversAndTools', 'FirefoxSeleniumProfile')
geckoDriverPath = os.path.join(theRootDir, 'DriversAndTools', 'geckodriver.exe')
profile = FirefoxProfile(profile_directory=ffProfilePath)
print (ffProfilePath)
print (geckoDriverPath)
b = browsers[request.param](firefox_profile=profile, capabilities=firefox_capabilities, executable_path=geckoDriverPath)
elif request.param == 'chrome':
desired_cap = DesiredCapabilities.CHROME
desired_cap['chromeOptions'] = {}
desired_cap['chromeOptions']['args'] = ['--disable-plugins', '--disable-extensions']
theRootDir = os.path.dirname(rootdir_ref.__file__)
chromeDriverPath = os.path.join(theRootDir, 'DriversAndTools', 'chromedriver.exe')
b = browsers[request.param](chromeDriverPath)
else:
b = browsers[request.param]()
request.addfinalizer(lambda *args: b.quit())
return b
#pytest.fixture(scope='function')
def driver(browser, url):
driver = browser
driver.maximize_window()
driver.get(url)
return driver
What I’d like to do is have a conftest file in each Test Folder instead of the ProjRoot. But if I take this existing conftest file and put it in each test folder and then run pytest from the project root using
python –m pytest
letting pytest pickup the test directories from pytest.ini (expecting the test folders to run with their respectively contained conftest files) I have issues with the parser.addoption --url already having been added. The end of the error message is:
ClientScripts\conftest.py:19: in pytest_addoption
parser.addoption('--url', default='https://test1.coreplus.com.au/coreplus01')
..\..\..\VirtEnv\VirtEnv\lib\site-packages\_pytest\config.py:521: in addoption
self._anonymous.addoption(*opts, **attrs)
..\..\..\VirtEnv\VirtEnv\lib\site-packages\_pytest\config.py:746: in addoption
raise ValueError("option names %s already added" % conflict)
E ValueError: option names {'--url'} already added
The purpose of the --url addoption is so I can override the defaults in the conftest file at commandline if I want to point them all to a different url at the same time, but otherwise let them default to running to different url's as specified in their conftest files.
I had a similar issue.
Error was gone after removing all cached files and venv.
I'm trying to do some basic module setups on my server using Python. Its a bit difficult as I have no access to the internet.
This is my code
import sys
import os
from subprocess import CalledProcessError, STDOUT, check_output
def run_in_path(command, dir_path, env_var=''):
env_var = os.environ["PATH"] = os.environ["PATH"] + env_var
print(env_var)
try:
p = check_output(command, cwd=dir_path, stderr=STDOUT)
except CalledProcessError as e:
sys.stderr.write(e.output.decode("utf-8"))
sys.stderr.flush()
return e.returncode
else:
return 0
def main():
requests_install = run_in_path('python setup.py build',
'D:\installed_software\python modules\kennethreitz-requests-e95e173')
SQL_install = run_in_path('python setup.py install', # install SQL module pypyodbc
'D:\installed_software\python modules\pypyodbc-1.3.3\pypyodbc-1.3.3')
setup_tools = run_in_path('python setup.py install', # install setup tools
'D:\installed_software\python modules\setuptools-17.1.1')
psycopg2 = run_in_path('easy_install psycopg2-2.6.1.win-amd64-py3.3-pg9.4.4-release', # install setup tools
'D:\installed_software\python modules', ';C:\srv_apps\Python33\Scripts\easy_install.exe')
print('setup complete')
if __name__ == "__main__":
sys.exit(main())
now it gets tricky when i start trying to use easy install. It appears my env variables are not being used by my subprocess.check_output call
File "C:\srv_apps\Python33\lib\subprocess.py", line 1110, in _execute_child
raise WindowsError(*e.args)
FileNotFoundError: [WinError 2] The system cannot find the file specified
I don't want to have to upgrade to 3.4 where easy install is installed by default because my other modules are not supported on 3.4. My main challenge is the subprocess.check_call method does not take environment variables as an input and im wary of trying to use Popen() as I have never really got it to work successfully in the past. Any help would be greatly appreciated.
PATH should contain directories e.g., r'C:\Python33\Scripts', not files such as: r'C:\Python33\Scripts\easy_install.exe'
Don't hardcode utf-8 for an arbitrary command, you could enable text mode using universal_newlines parameter (not tested):
#!/usr/bin/env python3
import locale
import sys
from subprocess import CalledProcessError, STDOUT, check_output
def run(command, *, cwd=None, env=None):
try:
ignored = check_output(command, cwd=cwd, env=env,
stderr=STDOUT,
universal_newlines=True)
except CalledProcessError as e:
sys.stderr.write(e.output)
sys.stderr.flush()
return e.returncode
else:
return 0
Example:
import os
path_var = os.pathsep.join(os.environ.get('PATH', os.defpath), some_dir)
env = dict(os.environ, PATH=path_var)
run("some_command", cwd=some_path, env=env)
run("another_command", cwd=another_path, env=env)