fix: run referenced testcase in python

This commit is contained in:
debugtalk
2022-04-02 10:28:25 +08:00
parent d36c1cb987
commit eac548f1e7
14 changed files with 85 additions and 90 deletions

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.1.7
# NOTE: Generated By HttpRunner v4.0.0-alpha
# FROM: basic.yml

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.1.7
# NOTE: Generated By HttpRunner v4.0.0-alpha
# FROM: hooks.yml

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.1.7
# NOTE: Generated By HttpRunner v4.0.0-alpha
# FROM: load_image.yml

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.1.7
# NOTE: Generated By HttpRunner v4.0.0-alpha
# FROM: upload.yml

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.1.7
# NOTE: Generated By HttpRunner v4.0.0-alpha
# FROM: validate.yml

View File

@@ -63,7 +63,7 @@ def main():
)
subparsers = parser.add_subparsers(help="sub-command help")
sub_parser_run = init_parser_run(subparsers)
init_parser_run(subparsers)
sub_parser_make = init_make_parser(subparsers)
if len(sys.argv) == 1:

View File

@@ -5,7 +5,8 @@ import unittest
import pytest
from httprunner.cli import main
from httprunner import loader
from httprunner.cli import main, main_run
class TestCli(unittest.TestCase):
@@ -45,8 +46,17 @@ class TestCli(unittest.TestCase):
try:
os.chdir(os.path.join(cwd, "examples", "postman_echo"))
exit_code = pytest.main(
["-s", "request_methods/request_with_testcase_reference_test.py",]
["-s", "request_methods/request_with_testcase_reference_test.py"]
)
self.assertEqual(exit_code, 0)
finally:
os.chdir(cwd)
def test_run_testcase_with_abnormal_path(self):
loader.project_meta = None
exit_code = main_run(["examples/data/a-b.c/2 3.yml"])
self.assertEqual(exit_code, 0)
self.assertTrue(os.path.exists("examples/data/a_b_c/__init__.py"))
self.assertTrue(os.path.exists("examples/data/debugtalk.py"))
self.assertTrue(os.path.exists("examples/data/a_b_c/T1_test.py"))
self.assertTrue(os.path.exists("examples/data/a_b_c/T2_3_test.py"))

View File

@@ -1,11 +1,8 @@
import os
from enum import Enum
from typing import Any
from typing import Dict, Text, Union, Callable
from typing import List
from typing import Any, Callable, Dict, List, Text, Union
from pydantic import BaseModel, Field
from pydantic import HttpUrl
from pydantic import BaseModel, Field, HttpUrl
Name = Text
Url = Text
@@ -156,14 +153,14 @@ class SessionData(BaseModel):
class StepData(BaseModel):
"""teststep data, each step maybe corresponding to one request or one testcase"""
name: Text = "" # teststep name
step_type: Text = "" # teststep type, request or testcase
name: Text = "" # teststep name
step_type: Text = "" # teststep type, request or testcase
success: bool = False
data: Union[SessionData, List['StepData']] = None
elapsed: float = 0.0 # teststep elapsed time
content_size: float = 0 # response content size
elapsed: float = 0.0 # teststep elapsed time
content_size: float = 0 # response content size
export_vars: VariablesMapping = {}
attachment: Text = "" # teststep attachment
attachment: Text = "" # teststep attachment
StepData.update_forward_refs()

View File

@@ -2,6 +2,7 @@ import unittest
import requests
from httprunner.parser import Parser
from httprunner.response import ResponseObject
@@ -18,15 +19,16 @@ class TestResponse(unittest.TestCase):
]
},
)
self.resp_obj = ResponseObject(resp)
parser = Parser(functions_mapping={
'get_name': lambda: 'name',
"get_num": lambda x: x
})
self.resp_obj = ResponseObject(resp, parser)
def test_extract(self):
variables_mapping = {
'body': 'body'
}
functions_mapping = {
'get_name': lambda: 'name',
}
extract_mapping = self.resp_obj.extract(
{
"var_1": "body.json.locations[0]",
@@ -35,7 +37,6 @@ class TestResponse(unittest.TestCase):
"var_4": "$body.json.locations[3].${get_name()}",
},
variables_mapping=variables_mapping,
functions_mapping=functions_mapping,
)
self.assertEqual(extract_mapping["var_1"], {"name": "Seattle", "state": "WA"})
self.assertEqual(extract_mapping["var_2"], "Olympia")
@@ -62,9 +63,7 @@ class TestResponse(unittest.TestCase):
def test_validate_functions(self):
variables_mapping = {"index": 1}
functions_mapping = {"get_num": lambda x: x}
self.resp_obj.validate(
[{"eq": ["${get_num(0)}", 0]}, {"eq": ["${get_num($index)}", 1]},],
variables_mapping=variables_mapping,
functions_mapping=functions_mapping,
)

View File

@@ -16,9 +16,10 @@ from loguru import logger
from httprunner.client import HttpSession
from httprunner.config import Config
from httprunner.exceptions import ParamsError
from httprunner.loader import load_project_meta
from httprunner.models import (ProjectMeta, StepData, TConfig, TestCaseInOut,
TestCaseSummary, TestCaseTime, VariablesMapping)
from httprunner.loader import load_project_meta, load_testcase_file
from httprunner.models import (ProjectMeta, StepData, TConfig, TestCase,
TestCaseInOut, TestCaseSummary, TestCaseTime,
VariablesMapping)
from httprunner.parser import Parser
from httprunner.utils import merge_variables
@@ -175,11 +176,9 @@ class HttpRunner(object):
logger.info(f"run step end: {step.name()} <<<<<<\n")
def test_start(self, param: Dict = None):
def test_start(self, param: Dict = None) -> "HttpRunner":
"""main entrance, discovered by pytest"""
self.__init()
log_handler = logger.add(self.__log_path, level="DEBUG")
self.__parse_config(param)
if USE_ALLURE:
@@ -191,6 +190,7 @@ class HttpRunner(object):
f"Start to run testcase: {self.__config.name}, TestCase ID: {self.case_id}"
)
log_handler = logger.add(self.__log_path, level="DEBUG")
self.__start_at = time.time()
try:
# run step in sequential order

View File

@@ -1,40 +0,0 @@
import os
import unittest
from httprunner import loader
from httprunner.cli import main_run
from httprunner.runner import HttpRunner
class TestHttpRunner(unittest.TestCase):
def setUp(self):
loader.project_meta = None
self.runner = HttpRunner()
def test_run_testcase_by_path_request_only(self):
self.runner.run_path(
"examples/postman_echo/request_methods/request_with_functions.yml"
)
result = self.runner.get_summary()
self.assertTrue(result.success)
self.assertEqual(result.name, "request methods testcase with functions")
self.assertEqual(result.step_datas[0].name, "get with params")
self.assertEqual(len(result.step_datas), 3)
def test_run_testcase_by_path_ref_testcase(self):
self.runner.run_path(
"examples/postman_echo/request_methods/request_with_testcase_reference.yml"
)
result = self.runner.get_summary()
self.assertTrue(result.success)
self.assertEqual(result.name, "request methods testcase: reference testcase")
self.assertEqual(result.step_datas[0].name, "request with functions")
self.assertEqual(len(result.step_datas), 2)
def test_run_testcase_with_abnormal_path(self):
exit_code = main_run(["examples/data/a-b.c/2 3.yml"])
self.assertEqual(exit_code, 0)
self.assertTrue(os.path.exists("examples/data/a_b_c/__init__.py"))
self.assertTrue(os.path.exists("examples/data/debugtalk.py"))
self.assertTrue(os.path.exists("examples/data/a_b_c/T1_test.py"))
self.assertTrue(os.path.exists("examples/data/a_b_c/T2_3_test.py"))

View File

@@ -0,0 +1,16 @@
import unittest
from examples.postman_echo.request_methods.request_with_functions_test import TestCaseRequestWithFunctions
class TestRunRequest(unittest.TestCase):
def test_run_request(self):
runner = TestCaseRequestWithFunctions().test_start()
summary = runner.get_summary()
self.assertTrue(summary.success)
self.assertEqual(summary.name, "request methods testcase with functions")
self.assertEqual(len(summary.step_datas), 3)
self.assertEqual(summary.step_datas[0].name, "get with params")
self.assertEqual(summary.step_datas[1].name, "post raw text")
self.assertEqual(summary.step_datas[2].name, "post form data")

View File

@@ -1,16 +1,11 @@
import os
from typing import Text, Callable
from typing import Callable, Text
from loguru import logger
from httprunner import exceptions
from httprunner.loader import load_testcase_file
from httprunner.step_request import call_hooks
from httprunner import exceptions
from httprunner.models import IStep, StepData, TStep
from httprunner.runner import HttpRunner
from httprunner.models import (
TStep,
StepData
)
from httprunner.step_request import call_hooks
def run_step_testcase(runner: HttpRunner, step: TStep) -> StepData:
@@ -25,9 +20,8 @@ def run_step_testcase(runner: HttpRunner, step: TStep) -> StepData:
# TODO: override testcase with current step name/variables/export
ref_case_runner = HttpRunner()
ref_case_runner.config = step.testcase.config
ref_case_runner.teststeps = step.testcase.teststeps
# step.testcase is a referenced testcase, e.g. RequestWithFunctions
ref_case_runner = step.testcase()
ref_case_runner.with_session(runner.session) \
.with_case_id(runner.case_id) \
.with_variables(step_variables) \
@@ -49,7 +43,7 @@ def run_step_testcase(runner: HttpRunner, step: TStep) -> StepData:
return step_data
class StepRefCase(object):
class StepRefCase(IStep):
def __init__(self, step: TStep):
self.__step = step
@@ -95,13 +89,9 @@ class RunTestCase(object):
return self
def call(self, testcase: Callable) -> StepRefCase:
if hasattr(testcase, "config") and hasattr(testcase, "teststeps"):
if issubclass(testcase, HttpRunner):
# referenced testcase object
self.__step.testcase = testcase
elif isinstance(testcase, Text):
if not os.path.isfile(testcase):
raise exceptions.ParamsError(f"Invalid testcase path: {testcase}")
self.__step.testcase = load_testcase_file(testcase)
else:
raise exceptions.ParamsError(
f"Invalid teststep referenced testcase: {testcase}"

View File

@@ -0,0 +1,23 @@
import unittest
from httprunner.runner import HttpRunner
from httprunner.step_testcase import RunTestCase
from examples.postman_echo.request_methods.request_with_functions_test import TestCaseRequestWithFunctions
class TestRunTestCase(unittest.TestCase):
def setUp(self):
self.runner = HttpRunner()
def test_run_testcase_by_path(self):
step_data = RunTestCase("run referenced testcase").call(
TestCaseRequestWithFunctions
).run(self.runner)
self.assertTrue(step_data.success)
self.assertEqual(step_data.name, "run referenced testcase")
self.assertEqual(len(step_data.data), 3)
self.assertEqual(step_data.data[0].name, "get with params")
self.assertEqual(step_data.data[1].name, "post raw text")
self.assertEqual(step_data.data[2].name, "post form data")