diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b0f541c..36611042 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Release History +## 2.2.1 (2019-06-25) + +**Features** + +- add demo api/testcase/testsuite to new created scaffold project +- update default `.gitignore` of new created scaffold project +- add demo content to `debugtalk.py`/`.env` of new created scaffold project + +**Bugfixes** + +- fix extend with testcase reference in format version 2 +- fix ImportError when locustio is not installed +- fix YAMLLoadWarning by specify yaml loader + ## 2.2.0 (2019-06-24) **Features** diff --git a/httprunner/__about__.py b/httprunner/__about__.py index e3bd235e..df64ac93 100644 --- a/httprunner/__about__.py +++ b/httprunner/__about__.py @@ -1,7 +1,7 @@ __title__ = 'HttpRunner' __description__ = 'One-stop solution for HTTP(S) testing.' __url__ = 'https://github.com/HttpRunner/HttpRunner' -__version__ = '2.2.0' +__version__ = '2.2.1' __author__ = 'debugtalk' __author_email__ = 'mail@debugtalk.com' __license__ = 'Apache-2.0' diff --git a/httprunner/cli.py b/httprunner/cli.py index 888f6a97..2bafe0c8 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -91,14 +91,12 @@ def main_hrun(): def main_locust(): """ Performance test with locust: parse command line options and run commands. """ - # monkey patch ssl at beginning to avoid RecursionError when running locust. - from gevent import monkey; monkey.patch_ssl() - - import multiprocessing - import sys - from httprunner import logger - try: + # monkey patch ssl at beginning to avoid RecursionError when running locust. + from gevent import monkey; monkey.patch_ssl() + import multiprocessing + import sys + from httprunner import logger from httprunner import locusts except ImportError: msg = "Locust is not installed, install first and try again.\n" diff --git a/httprunner/loader.py b/httprunner/loader.py index 4093bb37..bd346d42 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -35,7 +35,7 @@ def load_yaml_file(yaml_file): """ load yaml file and check file content format """ with io.open(yaml_file, 'r', encoding='utf-8') as stream: - yaml_content = yaml.load(stream) + yaml_content = yaml.load(stream, Loader=yaml.FullLoader) _check_format(yaml_file, yaml_content) return yaml_content @@ -332,7 +332,18 @@ def __extend_with_testcase_ref(raw_testinfo): project_mapping["PWD"], *testcase_path.split("/") ) - testcase_dict = load_testcase(load_file(testcase_path)) + loaded_testcase = load_file(testcase_path) + + if isinstance(loaded_testcase, list): + # make compatible with version < 2.2.0 + testcase_dict = load_testcase(loaded_testcase) + elif isinstance(loaded_testcase, dict) and "teststeps" in loaded_testcase: + # format version 2, implemented in 2.2.0 + testcase_dict = load_testcase_v2(loaded_testcase) + else: + raise exceptions.FileFormatError( + "Invalid format testcase: {}".format(testcase_path)) + tests_def_mapping[testcase_path] = testcase_dict else: testcase_dict = tests_def_mapping[testcase_path] diff --git a/httprunner/utils.py b/httprunner/utils.py index e8e90747..f5f712c5 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -410,31 +410,114 @@ def create_scaffold(project_name): logger.color_print("Start to create new project: {}".format(project_name), "GREEN") logger.color_print("CWD: {}\n".format(os.getcwd()), "BLUE") - def create_path(path, ptype): + def create_folder(path): + os.makedirs(path) + msg = "created folder: {}".format(path) + logger.color_print(msg, "BLUE") + + def create_file(path, file_content=""): + with open(path, 'w') as f: + f.write(file_content) + msg = "created file: {}".format(path) + logger.color_print(msg, "BLUE") + + def create_path(path, ptype, file_content=""): if ptype == "folder": os.makedirs(path) elif ptype == "file": - open(path, 'w').close() + with open(path, 'w') as f: + f.write(file_content) - msg = "created {}: {}".format(ptype, path) - logger.color_print(msg, "BLUE") + 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" - path_list = [ - (project_name, "folder"), - (os.path.join(project_name, "api"), "folder"), - (os.path.join(project_name, "testcases"), "folder"), - (os.path.join(project_name, "testsuites"), "folder"), - (os.path.join(project_name, "reports"), "folder"), - (os.path.join(project_name, "debugtalk.py"), "file"), - (os.path.join(project_name, ".env"), "file") - ] - [create_path(p[0], p[1]) for p in path_list] +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" - # create .gitignore file - ignore_file = os.path.join(project_name, ".gitignore") - ignore_content = ".env\nreports/*" - with open(ignore_file, "w") as f: - f.write(ignore_content) +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): diff --git a/tests/testcases/create_user.v2.yml b/tests/testcases/create_user.v2.yml new file mode 100644 index 00000000..7f34c532 --- /dev/null +++ b/tests/testcases/create_user.v2.yml @@ -0,0 +1,22 @@ +config: + name: "create user and check result." + id: create_user + base_url: "http://127.0.0.1:5000" + variables: + uid: 9001 + device_sn: "TESTCASE_CREATE_XXX" + output: + - session_token + +teststeps: +- + name: setup and reset all (override) for $device_sn. + testcase: testcases/setup.yml + output: + - session_token + +- + name: create user and check result. + variables: + token: $session_token + testcase: testcases/deps/check_and_create.yml diff --git a/tests/testsuites/create_users.v2.json b/tests/testsuites/create_users.v2.json index de4d5d27..450a27aa 100644 --- a/tests/testsuites/create_users.v2.json +++ b/tests/testsuites/create_users.v2.json @@ -11,7 +11,7 @@ "testcases": [ { "name": "create user 1000 and check result.", - "testcase": "testcases/create_user.yml", + "testcase": "testcases/create_user.v2.yml", "variables": { "var_d": "$var_c", "var_c": "${gen_random_string(5)}", @@ -20,7 +20,7 @@ }, { "name": "create user 1001 and check result.", - "testcase": "testcases/create_user.yml", + "testcase": "testcases/create_user.v2.yml", "variables": { "var_d": "$var_c", "var_c": "${gen_random_string(5)}", diff --git a/tests/testsuites/create_users.v2.yml b/tests/testsuites/create_users.v2.yml index 0714d82f..8fcdd930 100644 --- a/tests/testsuites/create_users.v2.yml +++ b/tests/testsuites/create_users.v2.yml @@ -9,7 +9,7 @@ config: testcases: - name: create user 1000 and check result. - testcase: testcases/create_user.yml + testcase: testcases/create_user.v2.yml variables: uid: 1000 var_c: ${gen_random_string(5)} @@ -17,7 +17,7 @@ testcases: - name: create user 1001 and check result. - testcase: testcases/create_user.yml + testcase: testcases/create_user.v2.yml variables: uid: 1001 var_c: ${gen_random_string(5)}