mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
change: make startproject as hrun sub-command, usage: hrun startproject <project_name>
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
# Release History
|
||||
|
||||
## 3.0.2 (2020-04-09)
|
||||
## 3.0.2 (2020-04-12)
|
||||
|
||||
**Changed**
|
||||
|
||||
- replace jsonschema validation with pydantic
|
||||
- remove compatibility with testcase/testsuite format v1
|
||||
- make `startproject` as hrun sub-command, usage: `hrun startproject <project_name>`
|
||||
|
||||
## 3.0.1 (2020-03-24)
|
||||
|
||||
|
||||
@@ -6,64 +6,46 @@ from loguru import logger
|
||||
|
||||
from httprunner import __description__, __version__
|
||||
from httprunner.api import HttpRunner
|
||||
from httprunner.ext.scaffold import init_parser_scaffold, main_scaffold
|
||||
from httprunner.report import gen_html_report
|
||||
from httprunner.utils import create_scaffold
|
||||
|
||||
|
||||
def main():
|
||||
""" API test: parse command line options and run commands.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description=__description__)
|
||||
parser.add_argument(
|
||||
'-V', '--version', dest='version', action='store_true',
|
||||
help="show version")
|
||||
parser.add_argument(
|
||||
def init_parser_run(subparsers):
|
||||
sub_parser_run = subparsers.add_parser(
|
||||
"run", help="Run HttpRunner testcases.")
|
||||
|
||||
sub_parser_run.add_argument(
|
||||
'testfile_paths', nargs='*',
|
||||
help="Specify api/testcase/testsuite file paths to run.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--log-level', default='INFO',
|
||||
help="Specify logging level, default is INFO.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--log-file',
|
||||
help="Write logs to specified file path.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--dot-env-path',
|
||||
help="Specify .env file path, which is useful for keeping sensitive data.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--report-template',
|
||||
help="Specify report template path.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--report-dir',
|
||||
help="Specify report save directory.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--report-file',
|
||||
help="Specify report file path, this has higher priority than specifying report dir.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--save-tests', action='store_true', default=False,
|
||||
help="Save loaded/parsed/vars_out/summary json data to JSON files.")
|
||||
parser.add_argument(
|
||||
sub_parser_run.add_argument(
|
||||
'--failfast', action='store_true', default=False,
|
||||
help="Stop the test run on the first error or failure.")
|
||||
parser.add_argument(
|
||||
'--startproject',
|
||||
help="Specify new project name.")
|
||||
|
||||
args = parser.parse_args()
|
||||
return sub_parser_run
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
# no argument passed
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
if args.version:
|
||||
print(f"{__version__}")
|
||||
sys.exit(0)
|
||||
|
||||
project_name = args.startproject
|
||||
if project_name:
|
||||
create_scaffold(project_name)
|
||||
sys.exit(0)
|
||||
|
||||
def main_run(args):
|
||||
runner = HttpRunner(
|
||||
failfast=args.failfast,
|
||||
save_tests=args.save_tests,
|
||||
@@ -90,5 +72,45 @@ def main():
|
||||
sys.exit(err_code)
|
||||
|
||||
|
||||
def main():
|
||||
""" API test: parse command line options and run commands.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description=__description__)
|
||||
parser.add_argument(
|
||||
'-V', '--version', dest='version', action='store_true',
|
||||
help="show version")
|
||||
|
||||
subparsers = parser.add_subparsers(help='sub-command help')
|
||||
sub_parser_run = init_parser_run(subparsers)
|
||||
sub_parser_scaffold = init_parser_scaffold(subparsers)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version:
|
||||
print(f"{__version__}")
|
||||
sys.exit(0)
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
# hrun
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
elif sys.argv[1] == "run":
|
||||
# hrun run
|
||||
if len(sys.argv) == 2:
|
||||
sub_parser_run.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
main_run(args)
|
||||
|
||||
elif sys.argv[1] == "startproject":
|
||||
# hrun startproject
|
||||
if len(sys.argv) == 2:
|
||||
sub_parser_scaffold.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
main_scaffold(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
129
httprunner/ext/scaffold/__init__.py
Normal file
129
httprunner/ext/scaffold/__init__.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def init_parser_scaffold(subparsers):
|
||||
sub_parser_scaffold = subparsers.add_parser(
|
||||
"startproject", help="Create a new project with template structure.")
|
||||
sub_parser_scaffold.add_argument("project_name", type=str, nargs="?", help="Specify new project name.")
|
||||
return sub_parser_scaffold
|
||||
|
||||
|
||||
def create_scaffold(project_name):
|
||||
""" create scaffold with specified project name.
|
||||
"""
|
||||
if os.path.isdir(project_name):
|
||||
logger.warning(f"Folder {project_name} exists, please specify a new folder name.")
|
||||
return
|
||||
|
||||
logger.info(f"Start to create new project: {project_name}")
|
||||
logger.info(f"CWD: {os.getcwd()}")
|
||||
|
||||
def create_folder(path):
|
||||
os.makedirs(path)
|
||||
msg = f"created folder: {path}"
|
||||
logger.info(msg)
|
||||
|
||||
def create_file(path, file_content=""):
|
||||
with open(path, 'w') as f:
|
||||
f.write(file_content)
|
||||
msg = f"created file: {path}"
|
||||
logger.info(msg)
|
||||
|
||||
demo_api_content = """
|
||||
name: demo api
|
||||
variables:
|
||||
var1: value1
|
||||
var2: value2
|
||||
request:
|
||||
url: /api/path/$var1
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
json:
|
||||
key: $var2
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
"""
|
||||
demo_testcase_content = """
|
||||
config:
|
||||
name: "demo testcase"
|
||||
variables:
|
||||
device_sn: "ABC"
|
||||
username: ${ENV(USERNAME)}
|
||||
password: ${ENV(PASSWORD)}
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: demo step 1
|
||||
api: path/to/api1.yml
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: $device_sn
|
||||
extract:
|
||||
token: content.token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
-
|
||||
name: demo step 2
|
||||
api: path/to/api2.yml
|
||||
variables:
|
||||
token: $token
|
||||
"""
|
||||
demo_testsuite_content = """
|
||||
config:
|
||||
name: "demo testsuite"
|
||||
variables:
|
||||
device_sn: "XYZ"
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
testcases:
|
||||
-
|
||||
name: call demo_testcase with data 1
|
||||
testcase: path/to/demo_testcase.yml
|
||||
variables:
|
||||
device_sn: $device_sn
|
||||
-
|
||||
name: call demo_testcase with data 2
|
||||
testcase: path/to/demo_testcase.yml
|
||||
variables:
|
||||
device_sn: $device_sn
|
||||
"""
|
||||
ignore_content = "\n".join([
|
||||
".env",
|
||||
"reports/*",
|
||||
"__pycache__/*",
|
||||
"*.pyc",
|
||||
".python-version",
|
||||
"logs/*"
|
||||
])
|
||||
demo_debugtalk_content = """
|
||||
import time
|
||||
|
||||
def sleep(n_secs):
|
||||
time.sleep(n_secs)
|
||||
"""
|
||||
demo_env_content = "\n".join([
|
||||
"USERNAME=leolee",
|
||||
"PASSWORD=123456"
|
||||
])
|
||||
|
||||
create_folder(project_name)
|
||||
create_folder(os.path.join(project_name, "api"))
|
||||
create_folder(os.path.join(project_name, "testcases"))
|
||||
create_folder(os.path.join(project_name, "testsuites"))
|
||||
create_folder(os.path.join(project_name, "reports"))
|
||||
create_file(os.path.join(project_name, "api", "demo_api.yml"), demo_api_content)
|
||||
create_file(os.path.join(project_name, "testcases", "demo_testcase.yml"), demo_testcase_content)
|
||||
create_file(os.path.join(project_name, "testsuites", "demo_testsuite.yml"), demo_testsuite_content)
|
||||
create_file(os.path.join(project_name, "debugtalk.py"), demo_debugtalk_content)
|
||||
create_file(os.path.join(project_name, ".env"), demo_env_content)
|
||||
create_file(os.path.join(project_name, ".gitignore"), ignore_content)
|
||||
|
||||
|
||||
def main_scaffold(args):
|
||||
create_scaffold(args.project_name)
|
||||
sys.exit(0)
|
||||
19
httprunner/ext/scaffold/test_scaffold.py
Normal file
19
httprunner/ext/scaffold/test_scaffold.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from httprunner.ext.scaffold import create_scaffold
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
|
||||
def test_create_scaffold(self):
|
||||
project_name = "projectABC"
|
||||
create_scaffold(project_name)
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "api")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "testcases")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "testsuites")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "reports")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, "debugtalk.py")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, ".env")))
|
||||
shutil.rmtree(project_name)
|
||||
@@ -349,119 +349,6 @@ def print_info(info_mapping):
|
||||
logger.info(content)
|
||||
|
||||
|
||||
def create_scaffold(project_name):
|
||||
""" create scaffold with specified project name.
|
||||
"""
|
||||
if os.path.isdir(project_name):
|
||||
logger.warning(f"Folder {project_name} exists, please specify a new folder name.")
|
||||
return
|
||||
|
||||
logger.info(f"Start to create new project: {project_name}")
|
||||
logger.info(f"CWD: {os.getcwd()}")
|
||||
|
||||
def create_folder(path):
|
||||
os.makedirs(path)
|
||||
msg = f"created folder: {path}"
|
||||
logger.info(msg)
|
||||
|
||||
def create_file(path, file_content=""):
|
||||
with open(path, 'w') as f:
|
||||
f.write(file_content)
|
||||
msg = f"created file: {path}"
|
||||
logger.info(msg)
|
||||
|
||||
demo_api_content = """
|
||||
name: demo api
|
||||
variables:
|
||||
var1: value1
|
||||
var2: value2
|
||||
request:
|
||||
url: /api/path/$var1
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
json:
|
||||
key: $var2
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
"""
|
||||
demo_testcase_content = """
|
||||
config:
|
||||
name: "demo testcase"
|
||||
variables:
|
||||
device_sn: "ABC"
|
||||
username: ${ENV(USERNAME)}
|
||||
password: ${ENV(PASSWORD)}
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: demo step 1
|
||||
api: path/to/api1.yml
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: $device_sn
|
||||
extract:
|
||||
- token: content.token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
-
|
||||
name: demo step 2
|
||||
api: path/to/api2.yml
|
||||
variables:
|
||||
token: $token
|
||||
"""
|
||||
demo_testsuite_content = """
|
||||
config:
|
||||
name: "demo testsuite"
|
||||
variables:
|
||||
device_sn: "XYZ"
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
testcases:
|
||||
-
|
||||
name: call demo_testcase with data 1
|
||||
testcase: path/to/demo_testcase.yml
|
||||
variables:
|
||||
device_sn: $device_sn
|
||||
-
|
||||
name: call demo_testcase with data 2
|
||||
testcase: path/to/demo_testcase.yml
|
||||
variables:
|
||||
device_sn: $device_sn
|
||||
"""
|
||||
ignore_content = "\n".join([
|
||||
".env",
|
||||
"reports/*",
|
||||
"__pycache__/*",
|
||||
"*.pyc",
|
||||
".python-version",
|
||||
"logs/*"
|
||||
])
|
||||
demo_debugtalk_content = """
|
||||
import time
|
||||
|
||||
def sleep(n_secs):
|
||||
time.sleep(n_secs)
|
||||
"""
|
||||
demo_env_content = "\n".join([
|
||||
"USERNAME=leolee",
|
||||
"PASSWORD=123456"
|
||||
])
|
||||
|
||||
create_folder(project_name)
|
||||
create_folder(os.path.join(project_name, "api"))
|
||||
create_folder(os.path.join(project_name, "testcases"))
|
||||
create_folder(os.path.join(project_name, "testsuites"))
|
||||
create_folder(os.path.join(project_name, "reports"))
|
||||
create_file(os.path.join(project_name, "api", "demo_api.yml"), demo_api_content)
|
||||
create_file(os.path.join(project_name, "testcases", "demo_testcase.yml"), demo_testcase_content)
|
||||
create_file(os.path.join(project_name, "testsuites", "demo_testsuite.yml"), demo_testsuite_content)
|
||||
create_file(os.path.join(project_name, "debugtalk.py"), demo_debugtalk_content)
|
||||
create_file(os.path.join(project_name, ".env"), demo_env_content)
|
||||
create_file(os.path.join(project_name, ".gitignore"), ignore_content)
|
||||
|
||||
|
||||
def gen_cartesian_product(*args):
|
||||
""" generate cartesian product for lists
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from httprunner import exceptions, loader, utils
|
||||
@@ -210,17 +209,6 @@ class TestUtils(unittest.TestCase):
|
||||
self.assertEqual(id(new_data["c"]), id(data["c"]))
|
||||
# self.assertEqual(id(new_data["d"]), id(data["d"]))
|
||||
|
||||
def test_create_scaffold(self):
|
||||
project_name = "projectABC"
|
||||
utils.create_scaffold(project_name)
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "api")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "testcases")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "testsuites")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "reports")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, "debugtalk.py")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, ".env")))
|
||||
shutil.rmtree(project_name)
|
||||
|
||||
def test_cartesian_product_one(self):
|
||||
parameters_content_list = [
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user