def from_har_file( cls, path: Path, plugins: Sequence[Plugin], ts_plugins: Sequence[Plugin], short_name: bool, blacklist: Blacklist, ) -> "Scenario": """ Creates a Scenario given a HAR file. :raise SkippableScenarioError: if path is unreadable or not a HAR file """ try: with path.open() as file: har = json.load(file) requests = Request.all_from_har(har) tasks = Task.from_requests(requests, blacklist) # TODO: Remove this when Contract.OnTaskSequence is removed. tasks = plug.apply(ts_plugins, tasks) # TODO: Remove Task-to-Task2 conversion once both are merged. tasks = tuple( plug.apply(plugins, Task2.from_task(t)) for t in tasks) return Scenario( name=to_identifier( path.with_suffix("").name if short_name else str(path)), children=tuple(tasks), origin=path, weight=cls.weight_from_path(path), ) except (OSError, json.JSONDecodeError, UnicodeDecodeError) as err: raise SkippableScenarioError(path, err)
def test_runs_plugins_in_succession_on_input(self): @plugin(Contract.OnTask) def plugin_a(x: str) -> str: return x + "a" @plugin(Contract.OnTask) def plugin_b(x: str) -> str: return x + "b" assert apply((plugin_a, plugin_b), "") == "ab" assert apply((plugin_b, plugin_a, plugin_b), "") == "bab"
def locustfile_lines(scenarios: Sequence[Scenario], program_plugins: Sequence[Plugin]) -> Iterator[str]: """ Converts the provided scenarios into a stream of Python statements and iterate on the resulting lines. """ program = plug.apply(program_plugins, locust_program(scenarios)) for stmt in program: for line in stmt.lines(): yield str(line)
def apply_plugins(self, plugins: Sequence[Plugin]) -> "Scenario": """ Recursively builds a new scenario tree from the leaves by applying all plugins to each cloned scenario subtree. Does not do anything if plugins is empty. """ if not plugins: return self children = [ c.apply_plugins(plugins) if isinstance(c, Scenario) else c for c in self.children ] return plug.apply(plugins, self._replace(children=children))
def apply_plugins(self, plugins: Sequence[Plugin]) -> "Scenario": """ Recursively builds a new scenario tree from the leaves by applying all *plugins* to each cloned scenario subtree. Does not do anything if *plugins* is empty. :param plugins: the plugins to apply. See :ref:`Specifying-plugins` for details. """ if not plugins: return self children = [ c.apply_plugins(plugins) if isinstance(c, Scenario) else c for c in self.children ] return plug.apply(plugins, dataclasses.replace(self, children=children))
def test_return_plugin_result(self): @plugin(Contract.OnTask) def plugin_a(x: str) -> str: return x + "a" assert apply([plugin_a], "z") == "za"
def test_return_init_unchanged_without_plugins(self): x = object() assert apply([], x) is x
def test_it_renders_a_locustfile_template_with_plugin_change_task_name( self): @plugin(Contract.OnTask) def plugin_change_task_name(t: Task2) -> Task2: t.request.name = "changed_name" return t a_name = "some_task" a_request = MagicMock(spec=Request) a_request.method = HttpMethod.GET a_request.url = MagicMock(spec=SplitResult) a_request.url.scheme = "some_scheme" a_request.url.hostname = "some_hostname" a_request.url.path = "some_path" a_request.url.geturl() a_request.url.geturl.return_value = "some_url" a_request.headers = {"a": "b"} a_request.name = None task = plug.apply((plugin_change_task_name, ), Task(a_name, a_request)) scenario = Scenario(name="SomeScenario", children=[task], origin=None) scenario_group = Scenario(name="ScenarioGroup", children=[scenario], weight=2, origin=None) script = locustfile([scenario_group]) expected = string.Template(f""" # File automatically generated by Transformer v{__version__}: # https://github.com/zalando-incubator/Transformer import re from distutils.version import LooseVersion from locust import __version__ LOCUST_MAJOR_VERSION = LooseVersion(__version__).version[0] if LOCUST_MAJOR_VERSION >= 1: from locust import HttpUser from locust import SequentialTaskSet from locust import TaskSet from locust import task HttpLocust = HttpUser TaskSequence = SequentialTaskSet def seq_task(_): return task else: from locust import HttpLocust from locust import TaskSequence from locust import TaskSet from locust import seq_task from locust import task class ScenarioGroup(TaskSet): @task(1) class SomeScenario(TaskSequence): @seq_task(1) def some_task(self): response = self.client.get(url='some_url', name='changed_name', timeout=$TIMEOUT, allow_redirects=False, headers={{'a': 'b'}}) class LocustForScenarioGroup(HttpLocust): if LOCUST_MAJOR_VERSION >= 1: tasks = [ScenarioGroup] else: task_set = ScenarioGroup weight = 2 min_wait = 0 max_wait = 10 """).safe_substitute({"TIMEOUT": TIMEOUT}) assert expected.strip() == script.strip()