mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-14 12:19:39 +08:00
Merge branch 'master' into master
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
__version__ = "3.1.6"
|
||||
__version__ = "3.1.8-beta"
|
||||
__description__ = "One-stop solution for HTTP(S) testing."
|
||||
|
||||
# import firstly for monkey patch if needed
|
||||
|
||||
@@ -5,14 +5,13 @@ import sys
|
||||
|
||||
import pytest
|
||||
from loguru import logger
|
||||
from sentry_sdk import capture_message
|
||||
|
||||
from httprunner import __description__, __version__
|
||||
from httprunner.compat import ensure_cli_args
|
||||
from httprunner.ext.har2case import init_har2case_parser, main_har2case
|
||||
from httprunner.make import init_make_parser, main_make
|
||||
from httprunner.scaffold import init_parser_scaffold, main_scaffold
|
||||
from httprunner.utils import init_sentry_sdk
|
||||
from httprunner.utils import init_sentry_sdk, ga_client
|
||||
|
||||
init_sentry_sdk()
|
||||
|
||||
@@ -25,7 +24,7 @@ def init_parser_run(subparsers):
|
||||
|
||||
|
||||
def main_run(extra_args) -> enum.IntEnum:
|
||||
capture_message("start to run")
|
||||
ga_client.track_event("RunAPITests", "hrun")
|
||||
# keep compatibility with v2
|
||||
extra_args = ensure_cli_args(extra_args)
|
||||
|
||||
|
||||
@@ -181,19 +181,19 @@ class HttpSession(requests.Session):
|
||||
|
||||
try:
|
||||
client_ip, client_port = response.raw.connection.sock.getsockname()
|
||||
self.data.address.client_ip = client_ip
|
||||
self.data.address.client_port = client_port
|
||||
logger.debug(f"client IP: {client_ip}, Port: {client_port}")
|
||||
except AttributeError as ex:
|
||||
logger.warning(f"failed to get client address info: {ex}")
|
||||
except AttributeError:
|
||||
client_ip, client_port = response.raw.connection.sock.socket.getsockname()
|
||||
self.data.address.client_ip = client_ip
|
||||
self.data.address.client_port = client_port
|
||||
logger.debug(f"client IP: {client_ip}, Port: {client_port}")
|
||||
|
||||
try:
|
||||
server_ip, server_port = response.raw.connection.sock.getpeername()
|
||||
self.data.address.server_ip = server_ip
|
||||
self.data.address.server_port = server_port
|
||||
logger.debug(f"server IP: {server_ip}, Port: {server_port}")
|
||||
except AttributeError as ex:
|
||||
logger.warning(f"failed to get server address info: {ex}")
|
||||
except AttributeError:
|
||||
server_ip, server_port = response.raw.connection.sock.socket.getpeername()
|
||||
self.data.address.server_ip = server_ip
|
||||
self.data.address.server_port = server_port
|
||||
logger.debug(f"server IP: {server_ip}, Port: {server_port}")
|
||||
|
||||
# get length of the response content
|
||||
content_size = int(dict(response.headers).get("content-length") or 0)
|
||||
|
||||
@@ -10,7 +10,7 @@ Usage:
|
||||
"""
|
||||
|
||||
from httprunner.ext.har2case.core import HarParser
|
||||
from sentry_sdk import capture_message
|
||||
from httprunner.utils import ga_client
|
||||
|
||||
|
||||
def init_har2case_parser(subparsers):
|
||||
@@ -64,7 +64,7 @@ def main_har2case(args):
|
||||
else:
|
||||
output_file_type = "pytest"
|
||||
|
||||
capture_message(f"har2case {output_file_type}")
|
||||
ga_client.track_event("ConvertTests", f"har2case {output_file_type}")
|
||||
HarParser(har_source_file, args.filter, args.exclude, args.profile).gen_testcase(output_file_type)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -70,11 +70,8 @@ def prepare_locust_tests() -> List:
|
||||
def main_locusts():
|
||||
""" locusts entrance
|
||||
"""
|
||||
from httprunner.utils import init_sentry_sdk
|
||||
from sentry_sdk import capture_message
|
||||
|
||||
init_sentry_sdk()
|
||||
capture_message("start to run locusts")
|
||||
from httprunner.utils import ga_client
|
||||
ga_client.track_event("RunLoadTests", "locust")
|
||||
|
||||
# avoid print too much log details in console
|
||||
logger.remove()
|
||||
|
||||
@@ -4,23 +4,14 @@ import json
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
from typing import Tuple, Dict, Union, Text, List, Callable
|
||||
from typing import Callable, Dict, List, Text, Tuple, Union
|
||||
|
||||
import yaml
|
||||
from loguru import logger
|
||||
from pydantic import ValidationError
|
||||
|
||||
from httprunner import builtin, utils
|
||||
from httprunner import exceptions
|
||||
from httprunner.models import TestCase, ProjectMeta, TestSuite
|
||||
|
||||
try:
|
||||
# PyYAML version >= 5.1
|
||||
# ref: https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation
|
||||
yaml.warnings({"YAMLLoadWarning": False})
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
from httprunner import builtin, exceptions, utils
|
||||
from httprunner.models import ProjectMeta, TestCase, TestSuite
|
||||
|
||||
project_meta: Union[ProjectMeta, None] = None
|
||||
|
||||
@@ -30,7 +21,7 @@ def _load_yaml_file(yaml_file: Text) -> Dict:
|
||||
"""
|
||||
with open(yaml_file, mode="rb") as stream:
|
||||
try:
|
||||
yaml_content = yaml.load(stream)
|
||||
yaml_content = yaml.load(stream, Loader=yaml.FullLoader)
|
||||
except yaml.YAMLError as ex:
|
||||
err_msg = f"YAMLError:\nfile: {yaml_file}\nerror: {ex}"
|
||||
logger.error(err_msg)
|
||||
@@ -130,6 +121,9 @@ def load_dot_env_file(dot_env_path: Text) -> Dict:
|
||||
with open(dot_env_path, mode="rb") as fp:
|
||||
for line in fp:
|
||||
# maxsplit=1
|
||||
line = line.strip()
|
||||
if not len(line) or line.startswith(b"#"):
|
||||
continue
|
||||
if b"=" in line:
|
||||
variable, value = line.split(b"=", 1)
|
||||
elif b":" in line:
|
||||
@@ -450,4 +444,4 @@ def convert_relative_project_root_dir(abs_path: Text) -> Text:
|
||||
f"project_meta.RootDir: {_project_meta.RootDir}"
|
||||
)
|
||||
|
||||
return abs_path[len(_project_meta.RootDir) + 1 :]
|
||||
return abs_path[len(_project_meta.RootDir) + 1:]
|
||||
|
||||
@@ -2,29 +2,21 @@ import os
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Text, List, Tuple, Dict, Set, NoReturn
|
||||
from typing import Dict, List, NoReturn, Set, Text, Tuple
|
||||
|
||||
import jinja2
|
||||
from loguru import logger
|
||||
from sentry_sdk import capture_exception
|
||||
|
||||
from httprunner import exceptions, __version__
|
||||
from httprunner.compat import (
|
||||
ensure_testcase_v3_api,
|
||||
ensure_testcase_v3,
|
||||
convert_variables,
|
||||
ensure_path_sep,
|
||||
)
|
||||
from httprunner.loader import (
|
||||
load_folder_files,
|
||||
load_test_file,
|
||||
load_testcase,
|
||||
load_testsuite,
|
||||
load_project_meta,
|
||||
convert_relative_project_root_dir,
|
||||
)
|
||||
from httprunner import __version__, exceptions
|
||||
from httprunner.compat import (convert_variables, ensure_path_sep,
|
||||
ensure_testcase_v3, ensure_testcase_v3_api)
|
||||
from httprunner.loader import (convert_relative_project_root_dir,
|
||||
load_folder_files, load_project_meta,
|
||||
load_test_file, load_testcase, load_testsuite)
|
||||
from httprunner.response import uniform_validator
|
||||
from httprunner.utils import merge_variables, is_support_multiprocessing
|
||||
from httprunner.utils import (ga_client, is_support_multiprocessing,
|
||||
merge_variables)
|
||||
|
||||
""" cache converted pytest files, avoid duplicate making
|
||||
"""
|
||||
@@ -80,10 +72,10 @@ if __name__ == "__main__":
|
||||
def __ensure_absolute(path: Text) -> Text:
|
||||
if path.startswith("./"):
|
||||
# Linux/Darwin, hrun ./test.yml
|
||||
path = path[len("./") :]
|
||||
path = path[len("./"):]
|
||||
elif path.startswith(".\\"):
|
||||
# Windows, hrun .\\test.yml
|
||||
path = path[len(".\\") :]
|
||||
path = path[len(".\\"):]
|
||||
|
||||
path = ensure_path_sep(path)
|
||||
project_meta = load_project_meta(path)
|
||||
@@ -173,7 +165,7 @@ def format_pytest_with_black(*python_paths: Text) -> NoReturn:
|
||||
subprocess.run(["black", *python_paths])
|
||||
else:
|
||||
logger.warning(
|
||||
f"this system does not support multiprocessing well, format files one by one ..."
|
||||
"this system does not support multiprocessing well, format files one by one ..."
|
||||
)
|
||||
[subprocess.run(["black", path]) for path in python_paths]
|
||||
except subprocess.CalledProcessError as ex:
|
||||
@@ -590,6 +582,8 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
|
||||
if not tests_paths:
|
||||
return []
|
||||
|
||||
ga_client.track_event("ConvertTests", "hmake")
|
||||
|
||||
for tests_path in tests_paths:
|
||||
tests_path = ensure_path_sep(tests_path)
|
||||
if not os.path.isabs(tests_path):
|
||||
|
||||
@@ -3,7 +3,8 @@ import subprocess
|
||||
import sys
|
||||
|
||||
from loguru import logger
|
||||
from sentry_sdk import capture_message
|
||||
|
||||
from httprunner.utils import ga_client
|
||||
|
||||
|
||||
def init_parser_scaffold(subparsers):
|
||||
@@ -199,5 +200,5 @@ def sleep(n_secs):
|
||||
|
||||
|
||||
def main_scaffold(args):
|
||||
capture_message("startproject with scaffold")
|
||||
ga_client.track_event("Scaffold", "startproject")
|
||||
sys.exit(create_scaffold(args.project_name))
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import collections
|
||||
import copy
|
||||
import itertools
|
||||
import json
|
||||
import os.path
|
||||
import platform
|
||||
import uuid
|
||||
from multiprocessing import Queue
|
||||
import itertools
|
||||
from typing import Dict, List, Any, Union, Text
|
||||
from typing import Any, Dict, List, Text
|
||||
|
||||
import requests
|
||||
import sentry_sdk
|
||||
from loguru import logger
|
||||
|
||||
from httprunner import __version__
|
||||
from httprunner import exceptions
|
||||
from httprunner import __version__, exceptions
|
||||
from httprunner.models import VariablesMapping
|
||||
|
||||
|
||||
@@ -25,6 +25,48 @@ def init_sentry_sdk():
|
||||
scope.set_user({"id": uuid.getnode()})
|
||||
|
||||
|
||||
class GAClient(object):
|
||||
|
||||
version = '1' # GA API Version
|
||||
report_url = 'https://www.google-analytics.com/collect'
|
||||
report_debug_url = 'https://www.google-analytics.com/debug/collect' # used for debug
|
||||
|
||||
def __init__(self, tracking_id: Text):
|
||||
self.http_client = requests.Session()
|
||||
self.label = str(__version__)
|
||||
self.common_params = {
|
||||
'v': self.version,
|
||||
'tid': tracking_id, # Tracking ID / Property ID, XX-XXXXXXX-X
|
||||
'cid': uuid.getnode(), # Anonymous Client ID
|
||||
'ua': f'HttpRunner/{__version__}',
|
||||
}
|
||||
|
||||
def track_event(self, category: Text, action: Text, value: int = 0):
|
||||
data = {
|
||||
't': 'event', # Event hit type = event
|
||||
'ec': category, # Required. Event Category.
|
||||
'ea': action, # Required. Event Action.
|
||||
'el': self.label, # Optional. Event label, used as version.
|
||||
'ev': value, # Optional. Event value, must be non-negative integer
|
||||
}
|
||||
data.update(self.common_params)
|
||||
self.http_client.post(self.report_url, data=data)
|
||||
|
||||
def track_user_timing(self, category: Text, variable: Text, duration: int):
|
||||
data = {
|
||||
't': 'timing', # Event hit type = timing
|
||||
'utc': category, # Required. user timing category. e.g. jsonLoader
|
||||
'utv': variable, # Required. timing variable. e.g. load
|
||||
'utt': duration, # Required. time took duration.
|
||||
'utl': self.label, # Optional. user timing label, used as version.
|
||||
}
|
||||
data.update(self.common_params)
|
||||
self.http_client.post(self.report_url, data=data)
|
||||
|
||||
|
||||
ga_client = GAClient("UA-114587036-1")
|
||||
|
||||
|
||||
def set_os_environ(variables_mapping):
|
||||
""" set variables mapping to os.environ
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user