change: make startproject as hrun sub-command, usage: hrun startproject <project_name>

This commit is contained in:
debugtalk
2020-04-12 16:56:19 +08:00
parent 4a50c4b583
commit 2f73d5021b
6 changed files with 206 additions and 160 deletions

View File

@@ -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)

View File

@@ -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()

View 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)

View 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)

View File

@@ -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

View File

@@ -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 = [
[