Мне нужно запустить тестовый скрипт python для разных сред (разные URL-адреса). И мне нужно определить, какую переменную использовать из командной строки. В дальнейшем этот параметр будет использоваться в работе Jenkins.
script.py:
class TestLogin(unittest.TestCase):
@allure.step
def test_LoginValidation(self):
devURL = "http://url1/admin/login/"
stagingURL = "http://url2/admin/login/"
prodURL = "https://url3/admin/login"
driver.maximize_window()
driver.implicitly_wait(10)
driver.get(url)
lp = LoginPage(driver)
lp.login("login", "password")
time.sleep(2)
driver.quit()
В командной строке мне нужно написать
python script.py stagingURL
В результате в методе test_LoginValidation в driver.get (URL) будет использоваться url, который я определил в командной строке.






Вы ищете argparse. Это должно позволить вам делать именно то, что вы ищете, например:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('url', help = 'The URL to use for ...', type = str)
Это устанавливает URL-адрес в качестве обязательного аргумента, передаваемого функции, и устанавливает для него тип str (это поведение по умолчанию, но явное указание - это хорошо).
Затем вы можете извлечь аргументы, используя:
args = parser.parse_args()
specified_url = args.url
Отсюда вы можете продолжить как обычно. Если вы хотите сделать аргумент необязательным, но со значением по умолчанию, это также можно сделать с помощью argparse.
Использование переменных среды работает, но отладить его намного сложнее, особенно если вы ожидаете, что этот сценарий будет запускаться другой частью программного обеспечения. Argparse намного надежнее.
В этом ответе поможет пример.
Для этого можно использовать argparse:
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Description')
parser.add_argument('--dev',
dest='dev',
action='store_true',
help = "Help message")
parser.add_argument('--stage',
dest='stage',
action='store_true',
help = "Help message")
parser.add_argument('--prod',
dest='prod',
action='store_true',
help = "Help message")
parser.set_defaults(dev=True,
stage=False,
action=False)
args = parser.parse_args()
url = None
if args.dev:
url = "http://url1/admin/login/"
if args.stage:
url = "http://url2/admin/login/"
if args.prod:
url = "https://url3/admin/login"
# do something with the url
Это один из способов сделать это. Вы создаете некоторые параметры arg --dev, --stage, --prod, и по умолчанию для --dev установлено значение true. Вы также можете не иметь значения по умолчанию (просто установите dev=False).
Итак, в следующий раз вы можете запустить:
python program.py --dev
python program.py --stage
python program.py --prod
Возможно, вы захотите обработать случай, когда передано более одного флага.
Вы также можете сделать это так:
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Description')
parser.add_argument("--env",
choices = {"dev", "stage", "prod"},
help = "Some help message.")
args = parser.parse_args()
url = None
if args.env == "dev":
url = "http://url1/admin/login/"
elif args.env == "stage":
url = "http://url2/admin/login/"
elif args.env == "prod":
url = "https://url3/admin/login"
else:
print("Please specify the environment using --env flag.")
if url is not None:
print(url)
Пример:
$ python3 test2.py
Please specify the environment using --env flag.
$ python3 test2.py --env prod
https://url3/admin/login
$ python3 test2.py --env stage
http://url2/admin/login/
$ python3 test2.py --env dev
http://url1/admin/login/
$ python3 test2.py --env wrong
usage: test2.py [-h] [--env {stage,dev,prod}]
test2.py: error: argument --env: invalid choice: 'wrong' (choose from 'stage', 'dev', 'prod')
Вы можете узнать больше о argparseздесь.
Могу порекомендовать пакет click для создания CLI. Это действительно просто, хорошо документировано, имеет множество опций и, на мой взгляд, намного проще в использовании, чем argparse.
Пустой пример:
import click
@click.command()
@click.option(
'--count',
default=1,
help='Number of greetings.'
)
@click.option(
'--name',
prompt='Your name',
help='The person to greet.'
)
def hello(**options):
"""Simple program that greets NAME for a total of COUNT times."""
for x in range(options['count']):
click.echo('Hello %s!' % options['name'])
if __name__ == '__main__':
hello()
И как это выглядит при запуске:
$ python hello.py --count=3
Your name: John
Hello John!
Hello John!
Hello John!
Он автоматически генерирует красиво отформатированные справочные страницы:
$ python hello.py --help
Usage: hello.py [OPTIONS]
Simple program that greets NAME for a total of COUNT times.
Options:
--count INTEGER Number of greetings.
--name TEXT The person to greet.
--help Show this message and exit.
Вы можете получить библиотеку прямо из PyPI:
pip install click
Если вы хотите создать интерфейс командной строки только для параметризации модульного теста, вы можете рассмотреть возможность использования @pytest.mark.parametrize, который позволяет определять несколько наборов аргументов и фикстур в тестовой функции или классе.
Пример:
import pytest
class TestLogin(object):
@pytest.mark.parametrize("url", [
"http://url1/admin/login/",
"http://url2/admin/login/",
"https://url3/admin/login",
])
def test_LoginValidation(self, url):
driver.maximize_window()
driver.implicitly_wait(10)
driver.get(url)
lp = LoginPage(driver)
lp.login("login", "password")
time.sleep(2)
driver.quit()
Возможно, стоит включить в click фрагмент переключатели функций, который здесь и следует использовать.
@AdamSmith Спасибо за ответ! Я не хотел, чтобы пост был слишком длинным, поэтому я больше не добавлял фрагментов (это уже хорошо задокументировано). Вместо этого я предоставил альтернативное решение, которое также должно решить вариант использования OP.
В Jenkins это почти наверняка легче сделать, чем в Python. Вдобавок кажется логичным, что ваш конвейер DevOps контролирует расположение URI разработки, подготовки и выпуска (по крайней мере, в той мере, в какой это целесообразно).
def targetUrl = ''
switch (env.TARGET) {
case 'dev':
targetUrl = "http://url1/admin/login/"
break
// etc
}
sh "python script.py ${targetUrl}"
затем попросите скрипт python взглянуть на sys.argv[1] (который является первым переданным ему аргументом) и напрямую использовать этот URL.
Если вы хотите создать интерфейс командной строки только для параметризации модульного теста, вы можете рассмотреть возможность использования
@pytest.mark.parametrize, который позволяет определять несколько наборов аргументов и фикстур в тестовой функции или классе. Вы можете посмотреть мой ответ для более подробной информации. Кроме того, я добавил фиктивный пример того, как реализовать cli с помощью python click.