From 4f0055efb5f75eda05006f9b41aa945130aa6c24 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 20 Aug 2025 16:44:10 -0700 Subject: [PATCH] Stop gap CLI v2 - Remove implicit test session creation behavior and all the options used for them - That meant fail fast code became mostly no-op - Removed reading/writing .launchable --- launchable/commands/helper.py | 162 ---------------- launchable/commands/inspect/tests.py | 15 +- launchable/commands/record/attachment.py | 9 +- launchable/commands/record/build.py | 6 - launchable/commands/record/session.py | 25 +-- launchable/commands/record/tests.py | 180 ++---------------- launchable/commands/subset.py | 171 +++-------------- launchable/utils/fail_fast_mode.py | 49 ----- launchable/utils/session.py | 97 ---------- tests/cli_test_case.py | 5 - tests/commands/inspect/test_tests.py | 8 +- tests/commands/record/test_attachment.py | 4 - tests/commands/record/test_build.py | 14 -- tests/commands/record/test_tests.py | 13 +- tests/commands/test_helper.py | 72 ------- tests/data/ant/record_test_result.json | 5 +- tests/data/bazel/record_test_result.json | 5 +- ...ord_test_with_build_event_json_result.json | 5 +- ...with_multiple_build_event_json_result.json | 5 +- tests/data/behave/record_test_result.json | 5 +- tests/data/ctest/record_test_result.json | 5 +- tests/data/cts/record_test_result.json | 5 +- .../cucumber/record_test_json_result.json | 5 +- tests/data/cucumber/record_test_result.json | 5 +- tests/data/cypress/record_test_result.json | 5 +- tests/data/dotnet/record_test_result.json | 5 +- tests/data/flutter/record_test_result.json | 5 +- tests/data/go_test/record_test_result.json | 5 +- .../googletest/fail/record_test_result.json | 5 +- tests/data/googletest/record_test_result.json | 5 +- tests/data/gradle/recursion/expected.json | 5 +- tests/data/jest/record_test_result.json | 5 +- tests/data/maven/record_test_result.json | 5 +- tests/data/minitest/record_test_result.json | 5 +- .../nunit-reporter-bug-with-nested-type.json | 5 +- .../data/nunit/record_test_result-linux.json | 5 +- .../nunit/record_test_result-windows.json | 5 +- tests/data/playwright/record_test_result.json | 5 +- .../record_test_result_with_json.json | 5 +- tests/data/prove/record_test_result.json | 5 +- tests/data/pytest/record_test_result.json | 5 +- .../data/pytest/record_test_result_json.json | 5 +- ...rd_test_executed_only_one_file_result.json | 5 +- tests/data/robot/record_test_result.json | 5 +- tests/data/rspec/record_test_result.json | 5 +- tests/data/vitest/record_test_result.json | 5 +- tests/data/xctest/record_test_result.json | 5 +- tests/test_runners/test_adb.py | 8 +- tests/test_runners/test_bazel.py | 33 +--- tests/test_runners/test_ctest.py | 20 +- tests/test_runners/test_cucumber.py | 11 +- tests/test_runners/test_go_test.py | 16 +- tests/test_runners/test_gradle.py | 30 +-- tests/test_runners/test_jest.py | 16 +- tests/test_runners/test_prove.py | 8 +- tests/test_runners/test_raw.py | 44 ++--- tests/test_session.py | 31 +-- tests/utils/test_fail_fast_mode.py | 29 +-- 58 files changed, 140 insertions(+), 1096 deletions(-) delete mode 100644 tests/commands/test_helper.py diff --git a/launchable/commands/helper.py b/launchable/commands/helper.py index ebd83e887..196ef2854 100644 --- a/launchable/commands/helper.py +++ b/launchable/commands/helper.py @@ -1,169 +1,7 @@ -import datetime from time import time -from typing import Optional, Sequence, Tuple - -import click - -from launchable.utils.no_build import NO_BUILD_BUILD_NAME -from launchable.utils.tracking import TrackingClient - -from ..app import Application -from ..utils.launchable_client import LaunchableClient -from ..utils.session import read_build, read_session, validate_session_format - - -def require_session( - session: Optional[str], -) -> Optional[str]: - """Ascertain the contextual test session to operate a CLI command for. If one doesn't exit, fail. - - 1. If the user explicitly provides the session id via the `--session` option - 2. If the user gives no options, the current session ID is read from the session file tied to $PWD. - See https://github.com/cloudbees-oss/smart-tests-cli/pull/342 - """ - if session: - validate_session_format(session) - return session - - session = read_session(require_build()) - if session: - return session - - raise click.UsageError( - click.style( - "No saved test session found.\n" - "If you already created a test session on a different machine, use the --session option. " - "See https://docs.launchableinc.com/sending-data-to-launchable/managing-complex-test-session-layouts", - fg="yellow")) - - -def require_build() -> str: - """ - Like read_build() but fail if a build doesn't exist - """ - b = read_build() - if not b: - raise click.UsageError( - click.style( - "No saved build name found.\n" - "To fix this, run `launchable record build`.\n" - "If you already ran this command on a different machine, use the --session option. " - "See https://www.launchableinc.com/docs/sending-data-to-launchable/using-the-launchable-cli/" - "recording-test-results-with-the-launchable-cli/managing-complex-test-session-layouts/", - fg="yellow")) - return b - - -def find_or_create_session( - context: click.core.Context, - session: Optional[str], - build_name: Optional[str], - tracking_client: TrackingClient, - flavor: Sequence[Tuple[str, str]] = (), - is_observation: bool = False, - links: Sequence[Tuple[str, str]] = (), - is_no_build: bool = False, - lineage: Optional[str] = None, - test_suite: Optional[str] = None, - timestamp: Optional[datetime.datetime] = None, -) -> Optional[str]: - """Determine the test session ID to be used. - - 1. If the user explicitly provides the session id via the `--session` option - 2. If the user gives no options, the current session ID is read from the session file tied to $PWD, - or one is created from the current build name. See https://github.com/cloudbees-oss/smart-tests-cli/pull/342 - 3. The `--build` option is legacy compatible behaviour, in which case a session gets created and tied - to the build. This usage still requires a locally recorded build name that must match the specified name. - Kohsuke is not sure what the historical motivation for this behaviour is. - - Args: - session: The --session option value - build_name: The --build option value - flavor: The --flavor option values - is_observation: The --observation value - links: The --link option values - is_no_build: The --no-build option value - lineage: lineage option value - test_suite: --test-suite option value - """ - from .record.session import session as session_command - - if session: - validate_session_format(session) - _check_observation_mode_status(session, is_observation, tracking_client=tracking_client, app=context.obj) - return session - - if is_no_build: - context.invoke( - session_command, - build_name=NO_BUILD_BUILD_NAME, - save_session_file=True, - print_session=False, - flavor=flavor, - is_observation=is_observation, - links=links, - is_no_build=is_no_build, - lineage=lineage, - test_suite=test_suite, - ) - saved_build_name = read_build() - return read_session(str(saved_build_name)) - - saved_build_name = require_build() - - if build_name and saved_build_name != build_name: - raise click.UsageError( - click.style( - "The build name you provided ({}) is different from the last build name recorded on this machine ({}).\n" - "Make sure to run `launchable record build --name {}` before you run this command.\n" - "If you already recorded this build on a different machine, use the --session option instead of --build. " - "See https://www.launchableinc.com/docs/sending-data-to-launchable/using-the-launchable-cli/" - "recording-test-results-with-the-launchable-cli/managing-complex-test-session-layouts/".format( - build_name, saved_build_name, build_name), fg="yellow", )) - - session_id = read_session(saved_build_name) - if session_id: - _check_observation_mode_status(session_id, is_observation, tracking_client=tracking_client, app=context.obj) - return session_id - - context.invoke( - session_command, - build_name=saved_build_name, - save_session_file=True, - print_session=False, - flavor=flavor, - is_observation=is_observation, - links=links, - is_no_build=is_no_build, - lineage=lineage, - test_suite=test_suite, - timestamp=timestamp, - ) - return read_session(saved_build_name) def time_ns(): # time.time_ns() method is new in Python version 3.7 # As a workaround, we convert time.time() to nanoseconds. return int(time() * 1e9) - - -def _check_observation_mode_status(session: str, is_observation: bool, - tracking_client: TrackingClient, app: Optional[Application] = None): - if not is_observation: - return - - client = LaunchableClient(tracking_client=tracking_client, app=app) - res = client.request("get", session) - - # only check when the status code is 200 not to stop the command - if res.status_code == 200: - is_observation_in_recorded_session = res.json().get("isObservation", False) - if is_observation and not is_observation_in_recorded_session: - click.echo( - click.style( - "WARNING: --observation flag was ignored. Observation mode can only be enabled for a test session " - "during its initial creation. " - "Add `--observation` option to the `launchable record session` command instead.", - fg='yellow'), - err=True) diff --git a/launchable/commands/inspect/tests.py b/launchable/commands/inspect/tests.py index 4ff145d23..506e6bf90 100644 --- a/launchable/commands/inspect/tests.py +++ b/launchable/commands/inspect/tests.py @@ -9,8 +9,6 @@ from ...utils.authentication import ensure_org_workspace from ...utils.launchable_client import LaunchableClient -from ...utils.session import parse_session -from ..helper import require_session class TestResult(object): @@ -133,6 +131,7 @@ def display(self): '--test-session-id', 'test_session_id', help='test session id', + required=True, ) @click.option( '--json', @@ -142,18 +141,6 @@ def display(self): ) @click.pass_context def tests(context: click.core.Context, test_session_id: int, is_json_format: bool): - if (test_session_id is None): - try: - session = require_session(None) - _, test_session_id = parse_session(session) - except Exception: - click.echo( - click.style( - "test session id requires.\n" - "Use the --test-session-id option or execute after `launchable record tests` command.", - fg="yellow")) - return - client = LaunchableClient(app=context.obj) try: res = client.request( diff --git a/launchable/commands/record/attachment.py b/launchable/commands/record/attachment.py index 5ffb6de56..ff2704f08 100644 --- a/launchable/commands/record/attachment.py +++ b/launchable/commands/record/attachment.py @@ -1,9 +1,7 @@ -from typing import Optional - import click from ...utils.launchable_client import LaunchableClient -from ..helper import require_session +from ...utils.session import validate_session_format @click.command() @@ -12,17 +10,18 @@ 'session', help='In the format builds//test_sessions/', type=str, + required=True, ) @click.argument('attachments', nargs=-1) # type=click.Path(exists=True) @click.pass_context def attachment( context: click.core.Context, attachments, - session: Optional[str] = None + session: str ): client = LaunchableClient(app=context.obj) try: - session = require_session(session) + validate_session_format(session) for a in attachments: click.echo("Sending {}".format(a)) diff --git a/launchable/commands/record/build.py b/launchable/commands/record/build.py index 321aceeff..e3054f7e7 100644 --- a/launchable/commands/record/build.py +++ b/launchable/commands/record/build.py @@ -16,7 +16,6 @@ from ...utils.commands import Command from ...utils.fail_fast_mode import set_fail_fast_mode, warn_and_exit_if_fail_fast_mode from ...utils.launchable_client import LaunchableClient -from ...utils.session import clean_session_files, write_build from .commit import commit JENKINS_GIT_BRANCH_KEY = "GIT_BRANCH" @@ -126,8 +125,6 @@ def build( if not no_commit_collection and len(commits) != 0: sys.exit("--no-commit-collection must be specified when --commit is used") - clean_session_files(days_ago=14) - # Information we want to collect for each Git repository # The key data structure throughout the implementation of this command class Workspace: @@ -341,9 +338,6 @@ def compute_links(): res = client.request("post", "builds", payload=payload) res.raise_for_status() - # at this point we've successfully send the data, so it's OK to record this build - write_build(build_name) - return res.json().get("id", None) except Exception as e: tracking_client.send_error_event( diff --git a/launchable/commands/record/session.py b/launchable/commands/record/session.py index b5376e1a0..6a50ed906 100644 --- a/launchable/commands/record/session.py +++ b/launchable/commands/record/session.py @@ -13,10 +13,9 @@ from ...utils.click import KEY_VALUE from ...utils.commands import Command -from ...utils.fail_fast_mode import FailFastModeValidateParams, fail_fast_mode_validate, set_fail_fast_mode +from ...utils.fail_fast_mode import set_fail_fast_mode from ...utils.launchable_client import LaunchableClient from ...utils.no_build import NO_BUILD_BUILD_NAME -from ...utils.session import _session_file_path, read_build, write_session LAUNCHABLE_SESSION_DIR_KEY = 'LAUNCHABLE_SESSION_DIR' @@ -41,13 +40,6 @@ def _validate_session_name(ctx, param, value): type=str, metavar='BUILD_NAME' ) -@click.option( - '--save-file/--no-save-file', - 'save_session_file', - help='save session to file', - default=True, - metavar='SESSION_FILE' -) @click.option( "--flavor", "flavor", @@ -114,7 +106,6 @@ def _validate_session_name(ctx, param, value): def session( ctx: click.core.Context, build_name: str, - save_session_file: bool, print_session: bool = True, flavor: Sequence[Tuple[str, str]] = [], is_observation: bool = False, @@ -138,22 +129,10 @@ def session( client = LaunchableClient(app=ctx.obj, tracking_client=tracking_client) set_fail_fast_mode(client.is_fail_fast_mode()) - fail_fast_mode_validate(FailFastModeValidateParams( - command=Command.RECORD_SESSION, - build=build_name, - is_no_build=is_no_build, - test_suite=test_suite, - )) - if not is_no_build and not build_name: raise click.UsageError("Error: Missing option '--build'") if is_no_build: - build = read_build() - if build and build != "": - raise click.UsageError( - "The cli already created '{}'. If you want to use the '--no-build' option, please remove this file first.".format(_session_file_path())) # noqa: E501 - build_name = NO_BUILD_BUILD_NAME if session_name: @@ -226,8 +205,6 @@ def session( build_name = res.json().get("buildNumber", "") sub_path = "builds/{}/test_sessions".format(build_name) - if save_session_file: - write_session(build_name, "{}/{}".format(sub_path, session_id)) if print_session: # what we print here gets captured and passed to `--session` in # later commands diff --git a/launchable/commands/record/tests.py b/launchable/commands/record/tests.py index 64415692a..c1079a258 100644 --- a/launchable/commands/record/tests.py +++ b/launchable/commands/record/tests.py @@ -4,7 +4,7 @@ import re import xml.etree.ElementTree as ET from http import HTTPStatus -from typing import Callable, Dict, Generator, List, Optional, Sequence, Tuple, Union +from typing import Callable, Dict, Generator, List, Optional, Tuple, Union import click from dateutil.parser import parse @@ -16,16 +16,14 @@ from launchable.utils.tracking import Tracking, TrackingClient from ...testpath import FilePathNormalizer, TestPathComponent, unparse_test_path -from ...utils.click import DATETIME_WITH_TZ, KEY_VALUE, validate_past_datetime +from ...utils.click import DATETIME_WITH_TZ, validate_past_datetime from ...utils.commands import Command from ...utils.exceptions import InvalidJUnitXMLException -from ...utils.fail_fast_mode import (FailFastModeValidateParams, fail_fast_mode_validate, - set_fail_fast_mode, warn_and_exit_if_fail_fast_mode) +from ...utils.fail_fast_mode import set_fail_fast_mode, warn_and_exit_if_fail_fast_mode from ...utils.launchable_client import LaunchableClient from ...utils.logger import Logger -from ...utils.no_build import NO_BUILD_BUILD_NAME, NO_BUILD_TEST_SESSION_ID -from ...utils.session import parse_session, read_build -from ..helper import find_or_create_session, time_ns +from ...utils.session import parse_session, validate_session_format +from ..helper import time_ns from .case_event import CaseEvent, CaseEventType GROUP_NAME_RULE = re.compile("^[a-zA-Z0-9][a-zA-Z0-9_-]*$") @@ -58,15 +56,9 @@ def _validate_group(ctx, param, value): 'session', help='In the format builds//test_sessions/', type=str, + required=True, ) -@click.option( - '--build', - 'build_name', - help='build name', - type=str, - metavar='BUILD_NAME', - hidden=True, -) +# TODO: what does this option do? @click.option( '--subset-id', 'subsetting_id', @@ -79,15 +71,6 @@ def _validate_group(ctx, param, value): default=1000, type=int ) -@click.option( - "--flavor", - "flavor", - help='flavors', - metavar='KEY=VALUE', - type=KEY_VALUE, - default=(), - multiple=True, -) @click.option( "--no_base_path_inference", "no_base_path_inference", @@ -124,44 +107,6 @@ def _validate_group(ctx, param, value): is_flag=True, hidden=True, ) -@click.option( - '--link', - 'links', - help="Set external link of title and url", - multiple=True, - default=(), - type=KEY_VALUE, -) -@click.option( - '--no-build', - 'is_no_build', - help="If you want to only send test reports, please use this option", - is_flag=True, -) -@click.option( - '--session-name', - 'session_name', - help='test session name', - required=False, - type=str, - metavar='SESSION_NAME', -) -@click.option( - '--lineage', - 'lineage', - help='Set lineage name. This option value will be passed to the record session command if a session isn\'t created yet.', - required=False, - type=str, - metavar='LINEAGE', -) -@click.option( - '--test-suite', - 'test_suite', - help='Set test suite name. This option value will be passed to the record session command if a session isn\'t created yet.', # noqa: E501 - required=False, - type=str, - metavar='TEST_SUITE', -) @click.option( '--timestamp', 'timestamp', @@ -174,20 +119,13 @@ def _validate_group(ctx, param, value): def tests( context: click.core.Context, base_path: str, - session: Optional[str], - build_name: Optional[str], + session: str, post_chunk: int, subsetting_id: str, - flavor: Sequence[Tuple[str, str]], no_base_path_inference: bool, report_paths: bool, group: str, is_allow_test_before_build: bool, - links: Sequence[Tuple[str, str]] = (), - is_no_build: bool = False, - session_name: Optional[str] = None, - lineage: Optional[str] = None, - test_suite: Optional[str] = None, timestamp: Optional[datetime.datetime] = None, ): logger = Logger() @@ -200,70 +138,19 @@ def tests( client = LaunchableClient(test_runner=test_runner, app=context.obj, tracking_client=tracking_client) set_fail_fast_mode(client.is_fail_fast_mode()) - fail_fast_mode_validate(FailFastModeValidateParams( - command=Command.RECORD_TESTS, - session=session, - build=build_name, - flavor=flavor, - links=links, - is_no_build=is_no_build, - test_suite=test_suite, - )) - file_path_normalizer = FilePathNormalizer(base_path, no_base_path_inference=no_base_path_inference) - if is_no_build and (read_build() and read_build() != ""): - msg = 'The cli already created `.launchable` file.' \ - 'If you want to use `--no-build` option, please remove `.launchable` file before executing.' - tracking_client.send_error_event( - event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, - stack_trace=msg, - - ) - raise click.UsageError(message=msg) # noqa: E501 - - if is_no_build and session: - warn_and_exit_if_fail_fast_mode( - "WARNING: `--session` and `--no-build` are set.\nUsing --session option value ({}) and ignoring `--no-build` option".format(session), # noqa: E501 - ) - - is_no_build = False - try: - if is_no_build: - session_id = "builds/{}/test_sessions/{}".format(NO_BUILD_BUILD_NAME, NO_BUILD_TEST_SESSION_ID) - record_start_at = INVALID_TIMESTAMP - elif subsetting_id: + if subsetting_id: result = get_session_and_record_start_at_from_subsetting_id(subsetting_id, client) - session_id = result["session"] + # TODO: this overwrite of session doesn't feel right + session = result["session"] record_start_at = result["start_at"] - elif session_name: - if not build_name: - raise click.UsageError( - '--build option is required when you uses a --session-name option ') - - sub_path = "builds/{}/test_session_names/{}".format(build_name, session_name) - res = client.request("get", sub_path) - res.raise_for_status() - - session_id = "builds/{}/test_sessions/{}".format(build_name, res.json().get("id")) - record_start_at = get_record_start_at(session_id, client) else: - # The session_id must be back, so cast to str - session_id = str(find_or_create_session( - context=context, - session=session, - build_name=build_name, - flavor=flavor, - links=links, - lineage=lineage, - test_suite=test_suite, - timestamp=timestamp, - tracking_client=tracking_client)) - build_name = read_build() - record_start_at = get_record_start_at(session_id, client) - - build_name, test_session_id = parse_session(session_id) + validate_session_format(session) + record_start_at = get_record_start_at(session, client) + + build_name, test_session_id = parse_session(session) except Exception as e: tracking_client.send_error_event( event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, @@ -332,14 +219,6 @@ def session(self) -> str: def session(self, session: str): self._session = session - @property - def is_no_build(self) -> bool: - return self._is_no_build - - @is_no_build.setter - def is_no_build(self, is_no_build: bool): - self._is_no_build = is_no_build - @property def metadata_builder(self) -> CaseEvent.DataBuilder: """ @@ -415,8 +294,7 @@ def __init__(self, dry_run=False): self.is_allow_test_before_build = is_allow_test_before_build self.build_name = build_name self.test_session_id = test_session_id - self.session = session_id - self.is_no_build = is_no_build + self.session = session self.metadata_builder = CaseEvent.default_data_builder() def make_file_path_component(self, filepath) -> TestPathComponent: @@ -431,7 +309,6 @@ def report(self, junit_report_file: str): if ( not self.is_allow_test_before_build # nlqa: W503 - and not self.is_no_build # noqa: W503 and timestamp is None # noqa: W503 and self.check_timestamp # noqa: W503 and ctime.timestamp() < record_start_at.timestamp() # noqa: W503 @@ -456,7 +333,6 @@ def scan(self, base: str, pattern: str): def run(self): count = 0 # count number of test cases sent - is_observation = False def testcases(reports: List[str]) -> Generator[CaseEventType, None, None]: exceptions = [] @@ -484,9 +360,7 @@ def testcases(reports: List[str]) -> Generator[CaseEventType, None, None]: # generator that creates the payload incrementally def payload( cases: Generator[TestCase, None, None], - test_runner, group: str, - test_suite_name: str, - flavors: Dict[str, str]) -> Tuple[Dict[str, Union[str, List, dict, bool]], List[Exception]]: + test_runner, group: str) -> Tuple[Dict[str, Union[str, List, dict, bool]], List[Exception]]: nonlocal count cs = [] exs = [] @@ -505,11 +379,6 @@ def payload( "testRunner": test_runner, "group": group, "metadata": get_env_values(client), - "noBuild": self.is_no_build, - # NOTE: - # testSuite and flavors are applied only when the no-build option is enabled - "testSuite": test_suite_name, - "flavors": flavors, }, exs def send(payload: Dict[str, Union[str, List]]) -> None: @@ -528,16 +397,6 @@ def send(payload: Dict[str, Union[str, List]]) -> None: res.raise_for_status() - nonlocal is_observation - is_observation = res.json().get("testSession", {}).get("isObservation", False) - - # If don’t override build, test session and session_id, build and test session will be made per chunk request. - if is_no_build: - self.build_name = res.json().get("build", {}).get("build", NO_BUILD_BUILD_NAME) - self.test_session_id = res.json().get("testSession", {}).get("id", NO_BUILD_TEST_SESSION_ID) - self.session = "builds/{}/test_sessions/{}".format(self.build_name, self.test_session_id) - self.is_no_build = False - def recorded_result() -> Tuple[int, int, int, float]: test_count = 0 success_count = 0 @@ -580,8 +439,6 @@ def recorded_result() -> Tuple[int, int, int, float]: cases=chunk, test_runner=test_runner, group=group, - test_suite_name=test_suite if test_suite else "", - flavors=dict(flavor), ) send(p) @@ -631,9 +488,6 @@ def recorded_result() -> Tuple[int, int, int, float]: file_count, )) - if is_observation: - click.echo("(This test session is under observation mode)") - click.echo("") header = ["Files found", "Tests found", "Tests passed", "Tests failed", "Total duration (min)"] diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index e0ec48e4a..14d6fd71f 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -7,24 +7,22 @@ import sys from multiprocessing import Process from os.path import join -from typing import Any, Callable, Dict, List, Optional, Sequence, TextIO, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, TextIO, Tuple, Union import click from tabulate import tabulate from launchable.utils.authentication import get_org_workspace -from launchable.utils.session import parse_session +from launchable.utils.session import parse_session, validate_session_format from launchable.utils.tracking import Tracking, TrackingClient from ..app import Application from ..testpath import FilePathNormalizer, TestPath -from ..utils.click import DURATION, KEY_VALUE, PERCENTAGE, DurationType, PercentageType, ignorable_error +from ..utils.click import DURATION, PERCENTAGE, DurationType, PercentageType, ignorable_error from ..utils.commands import Command from ..utils.env_keys import REPORT_ERROR_KEY -from ..utils.fail_fast_mode import (FailFastModeValidateParams, fail_fast_mode_validate, - set_fail_fast_mode, warn_and_exit_if_fail_fast_mode) +from ..utils.fail_fast_mode import set_fail_fast_mode, warn_and_exit_if_fail_fast_mode from ..utils.launchable_client import LaunchableClient -from .helper import find_or_create_session from .test_path_writer import TestPathWriter # TODO: rename files and function accordingly once the PR landscape @@ -60,6 +58,7 @@ 'session', help='In the format builds//test_sessions/', type=str, + required=True, ) @click.option( '--base', @@ -68,29 +67,12 @@ type=click.Path(exists=True, file_okay=False), metavar="DIR", ) -@click.option( - '--build', - 'build_name', - help='build name', - type=str, - metavar='BUILD_NAME', - hidden=True, -) @click.option( '--rest', 'rest', help='Output the subset remainder to a file, e.g. `--rest=remainder.txt`', type=str, ) -@click.option( - "--flavor", - "flavor", - help='flavors', - metavar='KEY=VALUE', - type=KEY_VALUE, - default=(), - multiple=True, -) @click.option( "--split", "split", @@ -119,12 +101,6 @@ help='Ignore tests that were added recently.\n\nNOTICE: this option will ignore tests that you added just now as well', is_flag=True ) -@click.option( - "--observation", - "is_observation", - help="enable observation mode", - is_flag=True, -) @click.option( "--get-tests-from-previous-sessions", "is_get_tests_from_previous_sessions", @@ -150,36 +126,6 @@ help='Ignore flaky tests above the value set by this option. You can confirm flaky scores in WebApp', type=click.FloatRange(min=0, max=1.0), ) -@click.option( - '--link', - 'links', - help="Set external link of title and url", - multiple=True, - default=(), - type=KEY_VALUE, -) -@click.option( - "--no-build", - "is_no_build", - help="If you want to only send test reports, please use this option", - is_flag=True, -) -@click.option( - '--session-name', - 'session_name', - help='test session name', - required=False, - type=str, - metavar='SESSION_NAME', -) -@click.option( - '--lineage', - 'lineage', - help='Set lineage name. This option value will be passed to the record session command if a session isn\'t created yet.', - required=False, - type=str, - metavar='LINEAGE', -) @click.option( "--prioritize-tests-failed-within-hours", "prioritize_tests_failed_within_hours", @@ -193,14 +139,6 @@ required=False, type=click.File('r'), ) -@click.option( - '--test-suite', - 'test_suite', - help='Set test suite name. This option value will be passed to the record session command if a session isn\'t created yet.', # noqa: E501 - required=False, - type=str, - metavar='TEST_SUITE', -) @click.option( "--get-tests-from-guess", "is_get_tests_from_guess", @@ -211,29 +149,21 @@ def subset( context: click.core.Context, target: Optional[PercentageType], - session: Optional[str], + session: str, base_path: Optional[str], - build_name: Optional[str], rest: str, duration: Optional[DurationType], - flavor: Sequence[Tuple[str, str]], confidence: Optional[PercentageType], goal_spec: Optional[str], split: bool, no_base_path_inference: bool, ignore_new_tests: bool, - is_observation: bool, is_get_tests_from_previous_sessions: bool, is_output_exclusion_rules: bool, is_non_blocking: bool, ignore_flaky_tests_above: Optional[float], - links: Sequence[Tuple[str, str]] = (), - is_no_build: bool = False, - session_name: Optional[str] = None, - lineage: Optional[str] = None, prioritize_tests_failed_within_hours: Optional[int] = None, prioritized_tests_mapping_file: Optional[TextIO] = None, - test_suite: Optional[str] = None, is_get_tests_from_guess: bool = False, ): app = context.obj @@ -244,16 +174,6 @@ def subset( tracking_client=tracking_client) set_fail_fast_mode(client.is_fail_fast_mode()) - fail_fast_mode_validate(FailFastModeValidateParams( - command=Command.SUBSET, - session=session, - build=build_name, - flavor=flavor, - is_observation=is_observation, - links=links, - is_no_build=is_no_build, - test_suite=test_suite, - )) def print_error_and_die(msg: str, event: Tracking.ErrorEvent): click.echo(click.style(msg, fg="red"), err=True) @@ -273,8 +193,9 @@ def warn(msg: str): Tracking.ErrorEvent.USER_ERROR ) - if is_observation and is_output_exclusion_rules: - warn("--observation and --output-exclusion-rules are set. No output will be generated.") + # TODO: this is a loss of error check + # if is_observation and is_output_exclusion_rules: + # warn("--observation and --output-exclusion-rules are set. No output will be generated.") if prioritize_tests_failed_within_hours is not None and prioritize_tests_failed_within_hours > 0: if ignore_new_tests or (ignore_flaky_tests_above is not None and ignore_flaky_tests_above > 0): @@ -283,36 +204,8 @@ def warn(msg: str): Tracking.ErrorEvent.INTERNAL_CLI_ERROR ) - if is_no_build and session: - warn_and_exit_if_fail_fast_mode( - "WARNING: `--session` and `--no-build` are set.\nUsing --session option value ({}) and ignoring `--no-build` option".format(session)) # noqa: E501 - is_no_build = False - - session_id = None - try: - if session_name: - if not build_name: - raise click.UsageError( - '--build option is required when you use a --session-name option ') - sub_path = "builds/{}/test_session_names/{}".format(build_name, session_name) - client = LaunchableClient(test_runner=context.invoked_subcommand, app=context.obj, tracking_client=tracking_client) - res = client.request("get", sub_path) - res.raise_for_status() - session_id = "builds/{}/test_sessions/{}".format(build_name, res.json().get("id")) - else: - session_id = find_or_create_session( - context=context, - session=session, - build_name=build_name, - flavor=flavor, - is_observation=is_observation, - links=links, - is_no_build=is_no_build, - lineage=lineage, - tracking_client=tracking_client, - test_suite=test_suite, - ) + validate_session_format(session) except click.UsageError as e: print_error_and_die(str(e), Tracking.ErrorEvent.USER_ERROR) except Exception as e: @@ -327,23 +220,22 @@ def warn(msg: str): click.echo(ignorable_error(e), err=True) if is_non_blocking: - if (not is_observation) and session_id: - try: - client = LaunchableClient( - app=app, - tracking_client=tracking_client) - res = client.request("get", session_id) - is_observation_in_recorded_session = res.json().get("isObservation", False) - if not is_observation_in_recorded_session: - print_error_and_die( - "You have to specify --observation option to use non-blocking mode", - Tracking.ErrorEvent.INTERNAL_CLI_ERROR) - except Exception as e: - tracking_client.send_error_event( - event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, - stack_trace=str(e), - ) - click.echo(ignorable_error(e), err=True) + try: + client = LaunchableClient( + app=app, + tracking_client=tracking_client) + res = client.request("get", session) + is_observation_in_recorded_session = res.json().get("isObservation", False) + if not is_observation_in_recorded_session: + print_error_and_die( + "You have to specify --observation option to use non-blocking mode", + Tracking.ErrorEvent.INTERNAL_CLI_ERROR) + except Exception as e: + tracking_client.send_error_event( + event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR, + stack_trace=str(e), + ) + click.echo(ignorable_error(e), err=True) file_path_normalizer = FilePathNormalizer(base_path, no_base_path_inference=no_base_path_inference) @@ -544,7 +436,7 @@ def request_subset(self) -> SubsetResult: # TODO: remove this line when API response return response # within 300 sec timeout = (5, 300) - payload = self.get_payload(str(session_id), target, duration, str(test_runner)) + payload = self.get_payload(session, target, duration, str(test_runner)) if is_non_blocking: # Create a new process for requesting a subset. @@ -586,12 +478,7 @@ def run(self): Tracking.ErrorEvent.USER_ERROR) # When Error occurs, return the test name as it is passed. - if not session_id: - # Session ID in --session is missing. It might be caused by - # Launchable API errors. - subset_result = SubsetResult.from_test_paths(self.test_paths) - else: - subset_result = self.request_subset() + subset_result = self.request_subset() if len(subset_result.subset) == 0: warn_and_exit_if_fail_fast_mode("Error: no tests found matching the path.") @@ -619,7 +506,7 @@ def run(self): if "subset" not in summary.keys() or "rest" not in summary.keys(): return - build_name, test_session_id = parse_session(session_id) + build_name, test_session_id = parse_session(session) org, workspace = get_org_workspace() header = ["", "Candidates", diff --git a/launchable/utils/fail_fast_mode.py b/launchable/utils/fail_fast_mode.py index e24d580ee..edcb07120 100644 --- a/launchable/utils/fail_fast_mode.py +++ b/launchable/utils/fail_fast_mode.py @@ -45,55 +45,6 @@ def __init__(self, command: Command, build: Optional[str] = None, is_no_build: b self.flavor = flavor -def fail_fast_mode_validate(params: FailFastModeValidateParams): - if not is_fail_fast_mode(): - return - - if params.command == Command.RECORD_SESSION: - _validate_record_session(params) - if params.command == Command.SUBSET: - _validate_subset(params) - if params.command == Command.RECORD_TESTS: - _validate_record_tests(params) - - -def _validate_require_session_option(params: FailFastModeValidateParams) -> List[str]: - errors: List[str] = [] - cmd_name = params.command.display_name() - if params.session: - if params.test_suite: - errors.append("`--test-suite` option was ignored in the {} command. Add `--test-suite` option to the `record session` command instead.".format(cmd_name)) # noqa: E501 - - if params.is_observation: - errors.append( - "`--observation` was ignored in the {} command. Add `--observation` option to the `record session` command instead.".format(cmd_name)) # noqa: E501 - - if len(params.flavor) > 0: - errors.append( - "`--flavor` option was ignored in the {} command. Add `--flavor` option to the `record session` command instead.".format(cmd_name)) # noqa: E501 - - if len(params.links) > 0: - errors.append( - "`--link` option was ignored in the {} command. Add `link` option to the `record session` command instead.".format(cmd_name)) # noqa: E501 - - return errors - - -def _validate_record_session(params: FailFastModeValidateParams): - # Now, there isn't any validation for the `record session` command in fail-fast mode. - return - - -def _validate_subset(params: FailFastModeValidateParams): - errors = _validate_require_session_option(params) - _exit_if_errors(errors) - - -def _validate_record_tests(params: FailFastModeValidateParams): - errors = _validate_require_session_option(params) - _exit_if_errors(errors) - - def _exit_if_errors(errors: List[str]): if errors: msg = "\n".join(map(lambda x: click.style(x, fg='red'), errors)) diff --git a/launchable/utils/session.py b/launchable/utils/session.py index d94bff54a..fccda1863 100644 --- a/launchable/utils/session.py +++ b/launchable/utils/session.py @@ -1,102 +1,5 @@ -import json -import os -from pathlib import Path -from typing import Optional - from .exceptions import ParseSessionException -SESSION_DIR_KEY = 'LAUNCHABLE_SESSION_DIR' - - -def _session_file_dir() -> Path: - return Path(os.environ.get(SESSION_DIR_KEY) or os.getcwd()).expanduser() - - -def _session_file_path() -> Path: - return _session_file_dir() / ".launchable" - - -def read_build() -> Optional[str]: - f = _session_file_path() - try: - if not f.exists(): - return None - - with open(str(_session_file_path())) as session_file: - session = json.load(session_file) - return session.get("build") - - except Exception as e: - raise Exception("Can't read {}".format(f)) from e - - -def read_session(build_name: str) -> Optional[str]: - f = _session_file_path() - try: - if not f.exists(): - return None - - with open(str(_session_file_path())) as session_file: - session = json.load(session_file) - if build_name != session.get('build', None): - raise Exception("Build name is different from saved. input:{} saved:{}".format( - build_name, session.get('build', None))) - - return session.get("session") - - except Exception as e: - raise Exception("Can't read {}".format(f)) from e - - -def write_build(build_name: str) -> None: - try: - if not _session_file_dir().exists(): - _session_file_dir().mkdir(parents=True, exist_ok=True) - - session = {} - session["build"] = build_name - - with open(str(_session_file_path()), 'w') as session_file: - json.dump(session, session_file) - - except Exception as e: - raise Exception( - "Can't write to {}. Is the path writable? " - "If not, set the {} environment variable to specify an alternative directory for this file.".format( - _session_file_path(), - SESSION_DIR_KEY)) from e - - -def write_session(build_name: str, session_id: str) -> None: - try: - session = {} - session["build"] = build_name - session["session"] = session_id - - with open(str(_session_file_path()), 'w') as session_file: - json.dump(session, session_file) - - except Exception as e: - raise Exception( - "Can't write to {}. " - "Perhaps set the {} environment variable to specify an alternative writable path?".format( - _session_file_path(), SESSION_DIR_KEY)) from e - - -def remove_session() -> None: - """ - Call it after closing a session - """ - if _session_file_path().exists(): - _session_file_path().unlink() - - -def clean_session_files(days_ago: int = 0) -> None: - """ - Call it each build start - """ - remove_session() - def validate_session_format(session: str): # session format: diff --git a/tests/cli_test_case.py b/tests/cli_test_case.py index e79611cc5..6dd9eb0e7 100644 --- a/tests/cli_test_case.py +++ b/tests/cli_test_case.py @@ -1,7 +1,6 @@ import gzip import inspect import json -import os import shutil import tempfile import types @@ -15,7 +14,6 @@ from launchable.__main__ import main from launchable.utils.http_client import get_base_url -from launchable.utils.session import SESSION_DIR_KEY, clean_session_files class CliTestCase(unittest.TestCase): @@ -36,7 +34,6 @@ class CliTestCase(unittest.TestCase): def setUp(self): self.dir = tempfile.mkdtemp() - os.environ[SESSION_DIR_KEY] = self.dir self.maxDiff = None @@ -201,8 +198,6 @@ def get_test_files_dir(self): return file_name.parent.joinpath('../data/%s/' % stem).resolve() def tearDown(self): - clean_session_files() - del os.environ[SESSION_DIR_KEY] shutil.rmtree(self.dir) def cli(self, *args, **kwargs) -> click.testing.Result: diff --git a/tests/commands/inspect/test_tests.py b/tests/commands/inspect/test_tests.py index fb15c8b2b..57ba92eee 100644 --- a/tests/commands/inspect/test_tests.py +++ b/tests/commands/inspect/test_tests.py @@ -4,7 +4,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import write_session from tests.cli_test_case import CliTestCase @@ -151,9 +150,7 @@ def test_tests_without_test_session_id(self): self.organization, self.workspace, self.session_id), json=self.response_json, status=200) - - write_session(self.build_name, self.session) - result = self.cli('inspect', 'tests') + result = self.cli('inspect', 'tests', '--session', self.session) self.assertEqual(result.stdout, self.expect) @responses.activate @@ -165,6 +162,5 @@ def test_tests_json_format(self): self.workspace, self.session_id), json=self.response_json, status=200) - write_session(self.build_name, self.session) - result = self.cli('inspect', 'tests', "--json") + result = self.cli('inspect', 'tests', "--json", '--session', self.session) self.assertEqual(result.stdout, self.expect_json) diff --git a/tests/commands/record/test_attachment.py b/tests/commands/record/test_attachment.py index 2bf002e2c..6ca1a3615 100644 --- a/tests/commands/record/test_attachment.py +++ b/tests/commands/record/test_attachment.py @@ -6,7 +6,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import write_session from tests.cli_test_case import CliTestCase @@ -16,9 +15,6 @@ class AttachmentTest(CliTestCase): def test_attachment(self): TEST_CONTENT = b"Hello world" - # emulate launchable record build & session - write_session(self.build_name, self.session_id) - attachment = tempfile.NamedTemporaryFile(delete=False) attachment.write(TEST_CONTENT) attachment.close() diff --git a/tests/commands/record/test_build.py b/tests/commands/record/test_build.py index 5d6940867..7c64d74b8 100644 --- a/tests/commands/record/test_build.py +++ b/tests/commands/record/test_build.py @@ -4,7 +4,6 @@ import responses # type: ignore -from launchable.utils.session import read_build from tests.cli_test_case import CliTestCase @@ -30,7 +29,6 @@ def test_submodule(self, mock_check_output): ('c50f5de0f06fe16afa4fd1dd615e4903e40b42a2 refs/head/main\nc50f5de0f06fe16afa4fd1dd615e4903e40b42a2 refs/remotes/origin/main\n').encode(), # noqa: E501 ] - self.assertEqual(read_build(), None) result = self.cli("record", "build", "--no-commit-collection", "--name", self.build_name) self.assert_success(result) @@ -63,8 +61,6 @@ def test_submodule(self, mock_check_output): "timestamp": None }, payload) - self.assertEqual(read_build(), self.build_name) - @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) # to tests on GitHub Actions @@ -77,8 +73,6 @@ def test_no_submodule(self, mock_check_output): ('c50f5de0f06fe16afa4fd1dd615e4903e40b42a2').encode(), ] - self.assertEqual(read_build(), None) - result = self.cli("record", "build", "--no-commit-collection", "--no-submodules", "--name", self.build_name) self.assert_success(result) @@ -98,8 +92,6 @@ def test_no_submodule(self, mock_check_output): "timestamp": None }, payload) - self.assertEqual(read_build(), self.build_name) - @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) # to tests on GitHub Actions @@ -109,7 +101,6 @@ def test_no_git_directory(self): orig_dir = os.getcwd() try: os.chdir(self.dir) - self.assertEqual(read_build(), None) self.cli("record", "build", "--no-commit-collection", "--commit", ".=c50f5de0f06fe16afa4fd1dd615e4903e40b42a2", "--name", self.build_name) @@ -129,8 +120,6 @@ def test_no_git_directory(self): "links": [], "timestamp": None }, payload) - - self.assertEqual(read_build(), self.build_name) finally: os.chdir(orig_dir) @@ -278,7 +267,6 @@ def test_build_name_validation(self): @mock.patch.dict(os.environ, {"GITHUB_PULL_REQUEST_URL": ""}) @mock.patch('launchable.utils.subprocess.check_output') def test_with_timestamp(self, mock_check_output): - self.assertEqual(read_build(), None) result = self.cli( "record", "build", @@ -306,5 +294,3 @@ def test_with_timestamp(self, mock_check_output): "links": [], "timestamp": "2025-01-23T12:34:56+00:00" }, payload) - - self.assertEqual(read_build(), self.build_name) diff --git a/tests/commands/record/test_tests.py b/tests/commands/record/test_tests.py index 1e8c122e0..9d6b72c68 100644 --- a/tests/commands/record/test_tests.py +++ b/tests/commands/record/test_tests.py @@ -10,7 +10,6 @@ from launchable.commands.record.tests import INVALID_TIMESTAMP, parse_launchable_timeformat from launchable.utils.http_client import get_base_url from launchable.utils.no_build import NO_BUILD_BUILD_NAME, NO_BUILD_TEST_SESSION_ID -from launchable.utils.session import write_build, write_session from tests.cli_test_case import CliTestCase @@ -21,9 +20,6 @@ class TestsTest(CliTestCase): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_with_group_name(self): - # emulate launchable record build & session - write_session(self.build_name, self.session_id) - result = self.cli('record', 'tests', '--session', self.session, '--group', 'hoge', 'maven', str( self.report_files_dir) + "**/reports/") @@ -35,12 +31,9 @@ def test_with_group_name(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_filename_in_error_message(self): - # emulate launchable record build - write_build(self.build_name) - normal_xml = str(Path(__file__).parent.joinpath('../../data/broken_xml/normal.xml').resolve()) broken_xml = str(Path(__file__).parent.joinpath('../../data/broken_xml/broken.xml').resolve()) - result = self.cli('record', 'tests', '--build', self.build_name, 'file', normal_xml, broken_xml) + result = self.cli('record', 'tests', '--session', self.session, 'file', normal_xml, broken_xml) def remove_backslash(input: str) -> str: # Hack for Windowns. They containts double escaped backslash such @@ -99,11 +92,9 @@ def test_parse_launchable_timeformat(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_when_total_test_duration_zero(self): - write_build(self.build_name) - zero_duration_xml1 = str(Path(__file__).parent.joinpath('../../data/googletest/output_a.xml').resolve()) zero_duration_xml2 = str(Path(__file__).parent.joinpath('../../data/googletest/output_b.xml').resolve()) - result = self.cli('record', 'tests', '--build', self.build_name, 'googletest', zero_duration_xml1, zero_duration_xml2) + result = self.cli('record', 'tests', '--session', self.session, 'googletest', zero_duration_xml1, zero_duration_xml2) self.assert_success(result) self.assertIn("Total test duration is 0.", result.output) diff --git a/tests/commands/test_helper.py b/tests/commands/test_helper.py deleted file mode 100644 index 82a05c22f..000000000 --- a/tests/commands/test_helper.py +++ /dev/null @@ -1,72 +0,0 @@ - -import os -from io import StringIO -from unittest import mock - -import responses # type: ignore - -from launchable.commands.helper import _check_observation_mode_status -from launchable.utils.commands import Command -from launchable.utils.http_client import get_base_url -from launchable.utils.tracking import TrackingClient -from tests.cli_test_case import CliTestCase - - -class HelperTest(CliTestCase): - - @responses.activate - @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) - def test_check_observation_mode_status(self): - test_session = "builds/{}/test_sessions/{}".format( - self.build_name, - self.session_id, - ) - - tracking_client = TrackingClient(Command.RECORD_TESTS) - - with mock.patch('sys.stderr', new=StringIO()) as stderr: - _check_observation_mode_status(test_session, False, tracking_client=tracking_client) - print(stderr.getvalue()) - self.assertNotIn("WARNING:", stderr.getvalue()) - - request_path = "{}/intake/organizations/{}/workspaces/{}/{}".format( - get_base_url(), - self.organization, - self.workspace, - test_session, - ) - - with mock.patch('sys.stderr', new=StringIO()) as stderr: - responses.replace( - responses.GET, - request_path, - json={ - "isObservation": False - }, status=200) - - _check_observation_mode_status(test_session, True, tracking_client=tracking_client) - self.assertIn("WARNING:", stderr.getvalue()) - - with mock.patch('sys.stderr', new=StringIO()) as stderr: - responses.replace( - responses.GET, - request_path, - json={ - "isObservation": True - }, status=200) - - _check_observation_mode_status(test_session, True, tracking_client=tracking_client) - self.assertNotIn("WARNING:", stderr.getvalue()) - - with mock.patch('sys.stderr', new=StringIO()) as stderr: - responses.replace( - responses.GET, - request_path, - json={ - "isObservation": True - }, status=404) - - _check_observation_mode_status(test_session, False, tracking_client=tracking_client) - - # not check when status isn't 200 - self.assertNotIn("WARNING:", stderr.getvalue()) diff --git a/tests/data/ant/record_test_result.json b/tests/data/ant/record_test_result.json index fc12d05ae..0a64c91b3 100644 --- a/tests/data/ant/record_test_result.json +++ b/tests/data/ant/record_test_result.json @@ -56,8 +56,5 @@ } ], "testRunner": "ant", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/bazel/record_test_result.json b/tests/data/bazel/record_test_result.json index 0d8345d6d..1be5ba8aa 100644 --- a/tests/data/bazel/record_test_result.json +++ b/tests/data/bazel/record_test_result.json @@ -128,8 +128,5 @@ } ], "testRunner": "bazel", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/bazel/record_test_with_build_event_json_result.json b/tests/data/bazel/record_test_with_build_event_json_result.json index 1afb8e2bd..f14a60463 100644 --- a/tests/data/bazel/record_test_with_build_event_json_result.json +++ b/tests/data/bazel/record_test_with_build_event_json_result.json @@ -44,8 +44,5 @@ } ], "testRunner": "bazel", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/bazel/record_test_with_multiple_build_event_json_result.json b/tests/data/bazel/record_test_with_multiple_build_event_json_result.json index 073f2b4ca..1c57088f7 100644 --- a/tests/data/bazel/record_test_with_multiple_build_event_json_result.json +++ b/tests/data/bazel/record_test_with_multiple_build_event_json_result.json @@ -72,8 +72,5 @@ } ], "testRunner": "bazel", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/behave/record_test_result.json b/tests/data/behave/record_test_result.json index d02739bff..ba24e3676 100644 --- a/tests/data/behave/record_test_result.json +++ b/tests/data/behave/record_test_result.json @@ -24,8 +24,5 @@ } ], "testRunner": "behave", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/ctest/record_test_result.json b/tests/data/ctest/record_test_result.json index 9de48e1b2..76a400210 100644 --- a/tests/data/ctest/record_test_result.json +++ b/tests/data/ctest/record_test_result.json @@ -58,8 +58,5 @@ } ], "testRunner": "ctest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/cts/record_test_result.json b/tests/data/cts/record_test_result.json index c64dbce28..bbf7cc68e 100644 --- a/tests/data/cts/record_test_result.json +++ b/tests/data/cts/record_test_result.json @@ -244,8 +244,5 @@ } ], "testRunner": "cts", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/cucumber/record_test_json_result.json b/tests/data/cucumber/record_test_json_result.json index 959df5c78..61e9e8de6 100644 --- a/tests/data/cucumber/record_test_json_result.json +++ b/tests/data/cucumber/record_test_json_result.json @@ -494,8 +494,5 @@ } ], "testRunner": "cucumber", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/cucumber/record_test_result.json b/tests/data/cucumber/record_test_result.json index 6ccc9502b..a731da802 100644 --- a/tests/data/cucumber/record_test_result.json +++ b/tests/data/cucumber/record_test_result.json @@ -288,8 +288,5 @@ } ], "testRunner": "cucumber", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/cypress/record_test_result.json b/tests/data/cypress/record_test_result.json index 821f5a0ff..4de1be5f7 100644 --- a/tests/data/cypress/record_test_result.json +++ b/tests/data/cypress/record_test_result.json @@ -68,8 +68,5 @@ } ], "testRunner": "cypress", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/dotnet/record_test_result.json b/tests/data/dotnet/record_test_result.json index 90aa4df51..4a3744248 100644 --- a/tests/data/dotnet/record_test_result.json +++ b/tests/data/dotnet/record_test_result.json @@ -106,8 +106,5 @@ } ], "testRunner": "dotnet", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/flutter/record_test_result.json b/tests/data/flutter/record_test_result.json index 0f792fcb1..81de72a28 100644 --- a/tests/data/flutter/record_test_result.json +++ b/tests/data/flutter/record_test_result.json @@ -56,8 +56,5 @@ } ], "testRunner": "flutter", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/go_test/record_test_result.json b/tests/data/go_test/record_test_result.json index 96d42d6e9..de3c62dc4 100644 --- a/tests/data/go_test/record_test_result.json +++ b/tests/data/go_test/record_test_result.json @@ -172,8 +172,5 @@ } ], "testRunner": "go-test", - "group": "", - "noBuild": false, - "testSuite": "", - "flavors": {} + "group": "" } diff --git a/tests/data/googletest/fail/record_test_result.json b/tests/data/googletest/fail/record_test_result.json index 7b9b528c8..162c4ec66 100644 --- a/tests/data/googletest/fail/record_test_result.json +++ b/tests/data/googletest/fail/record_test_result.json @@ -56,8 +56,5 @@ } ], "testRunner": "googletest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/googletest/record_test_result.json b/tests/data/googletest/record_test_result.json index 2f2a1ffdf..a5e422c20 100644 --- a/tests/data/googletest/record_test_result.json +++ b/tests/data/googletest/record_test_result.json @@ -110,8 +110,5 @@ } ], "testRunner": "googletest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/gradle/recursion/expected.json b/tests/data/gradle/recursion/expected.json index 6798dba57..f6e1e2cd1 100644 --- a/tests/data/gradle/recursion/expected.json +++ b/tests/data/gradle/recursion/expected.json @@ -74,8 +74,5 @@ } ], "testRunner": "gradle", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/jest/record_test_result.json b/tests/data/jest/record_test_result.json index 74444ce0a..be3a43c72 100644 --- a/tests/data/jest/record_test_result.json +++ b/tests/data/jest/record_test_result.json @@ -148,8 +148,5 @@ } ], "testRunner": "jest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/maven/record_test_result.json b/tests/data/maven/record_test_result.json index b003cff7a..21c8fb4a6 100644 --- a/tests/data/maven/record_test_result.json +++ b/tests/data/maven/record_test_result.json @@ -74,8 +74,5 @@ } ], "testRunner": "maven", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/minitest/record_test_result.json b/tests/data/minitest/record_test_result.json index 4c7132af2..94ccc6a52 100644 --- a/tests/data/minitest/record_test_result.json +++ b/tests/data/minitest/record_test_result.json @@ -145,8 +145,5 @@ } ], "testRunner": "minitest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/nunit/nunit-reporter-bug-with-nested-type.json b/tests/data/nunit/nunit-reporter-bug-with-nested-type.json index 2a1c446e2..89a165223 100644 --- a/tests/data/nunit/nunit-reporter-bug-with-nested-type.json +++ b/tests/data/nunit/nunit-reporter-bug-with-nested-type.json @@ -35,8 +35,5 @@ ], "testRunner": "nunit", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/nunit/record_test_result-linux.json b/tests/data/nunit/record_test_result-linux.json index 3bd767984..1f7de1a94 100644 --- a/tests/data/nunit/record_test_result-linux.json +++ b/tests/data/nunit/record_test_result-linux.json @@ -105,8 +105,5 @@ } ], "testRunner": "nunit", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/nunit/record_test_result-windows.json b/tests/data/nunit/record_test_result-windows.json index f27561db4..1cd188ad1 100644 --- a/tests/data/nunit/record_test_result-windows.json +++ b/tests/data/nunit/record_test_result-windows.json @@ -105,8 +105,5 @@ } ], "testRunner": "nunit", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/playwright/record_test_result.json b/tests/data/playwright/record_test_result.json index 01d6d9616..7436ba8c7 100644 --- a/tests/data/playwright/record_test_result.json +++ b/tests/data/playwright/record_test_result.json @@ -1676,8 +1676,5 @@ } ], "testRunner": "playwright", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/playwright/record_test_result_with_json.json b/tests/data/playwright/record_test_result_with_json.json index ad9c2da1b..bed83f9fa 100644 --- a/tests/data/playwright/record_test_result_with_json.json +++ b/tests/data/playwright/record_test_result_with_json.json @@ -2402,8 +2402,5 @@ } ], "testRunner": "playwright", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/prove/record_test_result.json b/tests/data/prove/record_test_result.json index 286151e1e..7d3914ec2 100644 --- a/tests/data/prove/record_test_result.json +++ b/tests/data/prove/record_test_result.json @@ -128,8 +128,5 @@ } ], "testRunner": "prove", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/pytest/record_test_result.json b/tests/data/pytest/record_test_result.json index ba790eb71..4a1c84494 100644 --- a/tests/data/pytest/record_test_result.json +++ b/tests/data/pytest/record_test_result.json @@ -226,8 +226,5 @@ } ], "testRunner": "pytest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/pytest/record_test_result_json.json b/tests/data/pytest/record_test_result_json.json index e87897ea9..a07f61ea2 100644 --- a/tests/data/pytest/record_test_result_json.json +++ b/tests/data/pytest/record_test_result_json.json @@ -156,8 +156,5 @@ } ], "testRunner": "pytest", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/robot/record_test_executed_only_one_file_result.json b/tests/data/robot/record_test_executed_only_one_file_result.json index 2211ea60e..a97d538cb 100644 --- a/tests/data/robot/record_test_executed_only_one_file_result.json +++ b/tests/data/robot/record_test_executed_only_one_file_result.json @@ -56,8 +56,5 @@ } ], "testRunner": "robot", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/robot/record_test_result.json b/tests/data/robot/record_test_result.json index e9a327c36..f248e6ee3 100644 --- a/tests/data/robot/record_test_result.json +++ b/tests/data/robot/record_test_result.json @@ -110,8 +110,5 @@ } ], "testRunner": "robot", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/rspec/record_test_result.json b/tests/data/rspec/record_test_result.json index 76c1f380b..c34e3dc3c 100644 --- a/tests/data/rspec/record_test_result.json +++ b/tests/data/rspec/record_test_result.json @@ -354,8 +354,5 @@ } ], "testRunner": "rspec", - "group": "", - "noBuild": false, - "flavors": [], - "testSuite": "" + "group": "" } diff --git a/tests/data/vitest/record_test_result.json b/tests/data/vitest/record_test_result.json index 9960a7219..667d4f5d5 100644 --- a/tests/data/vitest/record_test_result.json +++ b/tests/data/vitest/record_test_result.json @@ -92,8 +92,5 @@ } ], "testRunner": "vitest", - "group": "", - "noBuild": false, - "testSuite": "", - "flavors": [] + "group": "" } diff --git a/tests/data/xctest/record_test_result.json b/tests/data/xctest/record_test_result.json index 048ba19aa..da6724da6 100644 --- a/tests/data/xctest/record_test_result.json +++ b/tests/data/xctest/record_test_result.json @@ -200,8 +200,5 @@ } ], "testRunner": "xctest", - "group": "", - "noBuild": false, - "testSuite": "", - "flavors": {} + "group": "" } diff --git a/tests/test_runners/test_adb.py b/tests/test_runners/test_adb.py index 0f7003146..20b7f4624 100644 --- a/tests/test_runners/test_adb.py +++ b/tests/test_runners/test_adb.py @@ -3,7 +3,6 @@ import responses # type: ignore -from launchable.utils.session import read_session, write_build from tests.cli_test_case import CliTestCase @@ -51,11 +50,6 @@ class AdbTest(CliTestCase): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', 'adb', input=self.subset_input) + result = self.cli('subset', '--session', self.session, '--target', '10%', 'adb', input=self.subset_input) self.assert_success(result) - - self.assertEqual(read_session(self.build_name), self.session) self.assert_subset_payload('subset_result.json') diff --git a/tests/test_runners/test_bazel.py b/tests/test_runners/test_bazel.py index 4ba4ff25f..f20e2f7ed 100644 --- a/tests/test_runners/test_bazel.py +++ b/tests/test_runners/test_bazel.py @@ -6,7 +6,6 @@ import responses # type: ignore -from launchable.utils.session import read_session, write_build from tests.cli_test_case import CliTestCase @@ -27,67 +26,49 @@ class BazelTest(CliTestCase): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', 'bazel', input=self.subset_input) + result = self.cli('subset', '--session', self.session, '--target', '10%', 'bazel', input=self.subset_input) self.assert_success(result) - self.assertEqual(read_session(self.build_name), self.session) self.assert_subset_payload('subset_result.json') @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_test(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'bazel', str(self.test_files_dir) + "/") + result = self.cli('record', 'tests', '--session', self.session, 'bazel', str(self.test_files_dir) + "/") self.assert_success(result) - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_result.json') @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_test_with_build_event_json_file(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'bazel', '--build-event-json', str( + result = self.cli('record', 'tests', '--session', self.session, 'bazel', '--build-event-json', str( self.test_files_dir.joinpath("build_event.json")), str(self.test_files_dir) + "/") self.assert_success(result) - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_with_build_event_json_result.json') @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_test_with_multiple_build_event_json_files(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'bazel', '--build-event-json', + result = self.cli('record', 'tests', '--session', self.session, + 'bazel', '--build-event-json', str(self.test_files_dir.joinpath("build_event.json")), '--build-event-json', str(self.test_files_dir.joinpath("build_event_rest.json")), str(self.test_files_dir) + "/") self.assert_success(result) - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_with_multiple_build_event_json_result.json') @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset_record_key_match(self): - # emulate launchable record build - write_build(self.build_name) - """ Test recorded test results contain subset's test path """ - result = self.cli('subset', '--target', '10%', 'bazel', input=self.subset_input) + result = self.cli('subset', '--session', self.session, '--target', '10%', 'bazel', input=self.subset_input) self.assert_success(result) subset_payload = json.loads(gzip.decompress(self.find_request('/subset').request.body).decode()) - result = self.cli('record', 'tests', 'bazel', str(self.test_files_dir) + "/") + result = self.cli('record', 'tests', '--session', self.session, 'bazel', str(self.test_files_dir) + "/") self.assert_success(result) record_payload = json.loads(gzip.decompress(self.find_request('/events').request.body).decode()) diff --git a/tests/test_runners/test_ctest.py b/tests/test_runners/test_ctest.py index 3e41ef124..7fa5c8907 100644 --- a/tests/test_runners/test_ctest.py +++ b/tests/test_runners/test_ctest.py @@ -6,7 +6,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import read_session, write_build from tests.cli_test_case import CliTestCase @@ -39,10 +38,7 @@ def test_subset_multiple_files(self): # Use a non-existing dir to check it creates a dir. output_dir = os.path.join(tempdir, 'subdir') - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', 'ctest', + result = self.cli('subset', '--session', self.session, '--target', '10%', 'ctest', '--output-regex-files', '--output-regex-files-dir=' + output_dir, '--output-regex-files-size=32', @@ -76,21 +72,15 @@ def test_subset_multiple_files(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset_without_session(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', 'ctest', str(self.test_files_dir.joinpath("ctest_list.json"))) + result = self.cli('subset', '--session', self.session, '--target', '10%', + 'ctest', str(self.test_files_dir.joinpath("ctest_list.json"))) self.assert_success(result) self.assert_subset_payload('subset_result.json') @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_test(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'ctest', str(self.test_files_dir) + "/Testing/**/Test.xml") + result = self.cli('record', 'tests', '--session', self.session, 'ctest', + str(self.test_files_dir) + "/Testing/**/Test.xml") self.assert_success(result) - - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_result.json') diff --git a/tests/test_runners/test_cucumber.py b/tests/test_runners/test_cucumber.py index 2b24b759c..5fb79d89d 100644 --- a/tests/test_runners/test_cucumber.py +++ b/tests/test_runners/test_cucumber.py @@ -5,7 +5,6 @@ import responses # type: ignore from launchable.test_runners.cucumber import _create_file_candidate_list, clean_uri -from launchable.utils.session import write_build from tests.cli_test_case import CliTestCase @@ -17,10 +16,7 @@ def test_record_test(self): for f in glob.iglob(str(self.test_files_dir.joinpath("report/*.xml")), recursive=True): reports.append(f) - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', '--base', str(self.test_files_dir), 'cucumber', *reports) + result = self.cli('record', 'tests', '--session', self.session, '--base', str(self.test_files_dir), 'cucumber', *reports) self.assert_success(result) self.assert_record_tests_payload('record_test_result.json') @@ -32,10 +28,7 @@ def test_record_test_from_json(self): for f in glob.iglob(str(self.test_files_dir.joinpath("report/*.json")), recursive=True): reports.append(f) - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'cucumber', "--json", *reports) + result = self.cli('record', 'tests', '--session', self.session, 'cucumber', "--json", *reports) self.assert_success(result) self.assert_record_tests_payload('record_test_json_result.json') diff --git a/tests/test_runners/test_go_test.py b/tests/test_runners/test_go_test.py index 066e5bbe0..2be8891e8 100644 --- a/tests/test_runners/test_go_test.py +++ b/tests/test_runners/test_go_test.py @@ -5,7 +5,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import read_session, write_build from tests.cli_test_case import CliTestCase @@ -22,16 +21,11 @@ def test_subset_with_session(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset_without_session(self): - # emulate launchable record build - write_build(self.build_name) - pipe = "TestExample1\nTestExample2\nTestExample3\nTestExample4\n" \ "ok github.com/launchableinc/rocket-car-gotest 0.268s" - result = self.cli('subset', '--target', '10%', 'go-test', input=pipe) + result = self.cli('subset', '--session', self.session, '--target', '10%', 'go-test', input=pipe) self.assert_success(result) - - self.assertEqual(read_session(self.build_name), self.session) self.assert_subset_payload('subset_result.json') @responses.activate @@ -45,13 +39,9 @@ def test_record_tests_with_session(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_tests_without_session(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'go-test', str(self.test_files_dir.joinpath('reportv1')) + "/") + result = self.cli('record', 'tests', '--session', self.session, 'go-test', + str(self.test_files_dir.joinpath('reportv1')) + "/") self.assert_success(result) - - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_result.json') @responses.activate diff --git a/tests/test_runners/test_gradle.py b/tests/test_runners/test_gradle.py index 1affb5275..9b6ce840a 100644 --- a/tests/test_runners/test_gradle.py +++ b/tests/test_runners/test_gradle.py @@ -6,7 +6,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import write_build from tests.cli_test_case import CliTestCase from tests.helper import ignore_warnings @@ -38,11 +37,8 @@ def test_subset_without_session(self): "isBrainless": False}, status=200) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( - 'subset', '--target', '10%', 'gradle', + 'subset', '--session', self.session, '--target', '10%', 'gradle', str(self.test_files_dir.joinpath('java/app/src/test').resolve())) # TODO: we need to assert on the request payload to make sure it found # test list all right @@ -86,11 +82,8 @@ def test_subset_rest(self): rest = tempfile.NamedTemporaryFile(delete=False) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( - 'subset', '--target', '10%', '--rest', rest.name, 'gradle', + 'subset', '--session', self.session, '--target', '10%', '--rest', rest.name, 'gradle', str(self.test_files_dir.joinpath('java/app/src/test/java').resolve())) self.assert_success(result) @@ -133,11 +126,9 @@ def test_subset_zero_input_subsetting(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( 'subset', + '--session', self.session, '--target', '10%', '--get-tests-from-previous-sessions', @@ -187,12 +178,9 @@ def test_subset_zero_input_subsetting_observation(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( 'subset', - '--target', + '--session', self.session, '--target', '10%', '--get-tests-from-previous-sessions', '--output-exclusion-rules', @@ -238,12 +226,9 @@ def test_subset_zero_input_subsetting_source_root(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( 'subset', - '--target', + '--session', self.session, '--target', '10%', '--get-tests-from-previous-sessions', '--output-exclusion-rules', @@ -288,12 +273,9 @@ def test_subset_split(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - result = self.cli( 'subset', - '--target', + '--session', self.session, '--target', '10%', '--split', 'gradle', diff --git a/tests/test_runners/test_jest.py b/tests/test_runners/test_jest.py index efa15c7dd..d2457d102 100644 --- a/tests/test_runners/test_jest.py +++ b/tests/test_runners/test_jest.py @@ -5,7 +5,6 @@ import responses # type: ignore from launchable.utils.http_client import get_base_url -from launchable.utils.session import write_build from tests.cli_test_case import CliTestCase from tests.helper import ignore_warnings @@ -32,10 +31,7 @@ class JestTest(CliTestCase): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_subset(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', '--base', + result = self.cli('subset', '--session', self.session, '--target', '10%', '--base', os.getcwd(), 'jest', input=self.subset_input) self.assert_success(result) self.assert_subset_payload('subset_result.json') @@ -62,10 +58,7 @@ def test_subset_split(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '20%', '--base', os.getcwd(), '--split', + result = self.cli('subset', '--session', self.session, '--target', '20%', '--base', os.getcwd(), '--split', 'jest', input=self.subset_input) self.assert_success(result) @@ -75,9 +68,6 @@ def test_subset_split(self): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_test(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'jest', str(self.test_files_dir.joinpath("junit.xml"))) + result = self.cli('record', 'tests', '--session', self.session, 'jest', str(self.test_files_dir.joinpath("junit.xml"))) self.assert_success(result) self.assert_record_tests_payload('record_test_result.json') diff --git a/tests/test_runners/test_prove.py b/tests/test_runners/test_prove.py index efc0b42f1..5a1e379d8 100644 --- a/tests/test_runners/test_prove.py +++ b/tests/test_runners/test_prove.py @@ -4,7 +4,6 @@ import responses # type: ignore from launchable.test_runners.prove import remove_leading_number_and_dash -from launchable.utils.session import read_session, write_build from tests.cli_test_case import CliTestCase @@ -32,11 +31,6 @@ class ProveTestTest(CliTestCase): @responses.activate @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) def test_record_tests(self): - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'prove', str(self.test_files_dir.joinpath('report.xml'))) + result = self.cli('record', 'tests', '--session', self.session, 'prove', str(self.test_files_dir.joinpath('report.xml'))) self.assert_success(result) - - self.assertEqual(read_session(self.build_name), self.session) self.assert_record_tests_payload('record_test_result.json') diff --git a/tests/test_runners/test_raw.py b/tests/test_runners/test_raw.py index fdaf60c73..a692d65c0 100644 --- a/tests/test_runners/test_raw.py +++ b/tests/test_runners/test_raw.py @@ -9,7 +9,6 @@ from dateutil.tz import tzlocal from launchable.utils.http_client import get_base_url -from launchable.utils.session import write_build from tests.cli_test_case import CliTestCase from tests.helper import ignore_warnings @@ -48,10 +47,7 @@ def test_subset(self): 'testcase=FooTest.Baz', ]) + '\n') - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('subset', '--target', '10%', + result = self.cli('subset', '--session', self.session, '--target', '10%', 'raw', test_path_file, mix_stderr=False) self.assert_success(result) @@ -100,13 +96,12 @@ def test_subset_get_tests_from_previous_sessions(self): }, status=200) - # emulate launchable record build - write_build(self.build_name) - # Don't use with for Windows environment rest = tempfile.NamedTemporaryFile(mode="+w", encoding="utf-8", delete=False) result = self.cli( 'subset', + '--session', + self.session, '--target', '10%', '--get-tests-from-previous-sessions', @@ -217,10 +212,16 @@ def test_record_tests(self): '}', ]) + '\n') - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'raw', test_path_file, test_path_file2, test_path_file3, mix_stderr=False) + result = self.cli( + 'record', + 'tests', + '--session', + self.session, + 'raw', + test_path_file, + test_path_file2, + test_path_file3, + mix_stderr=False) self.assert_success(result) # Check request body @@ -284,9 +285,6 @@ def test_record_tests(self): ], "testRunner": "raw", "group": "", - "noBuild": False, - "flavors": [], - "testSuite": "", }) @responses.activate @@ -320,10 +318,15 @@ def test_record_tests_junit_xml(self): '', ]) + '\n') - # emulate launchable record build - write_build(self.build_name) - - result = self.cli('record', 'tests', 'raw', test_path_file, test_path_file2, mix_stderr=False) + result = self.cli( + 'record', + 'tests', + '--session', + self.session, + 'raw', + test_path_file, + test_path_file2, + mix_stderr=False) if result.exit_code != 0: self.assertEqual( result.exit_code, @@ -364,9 +367,6 @@ def test_record_tests_junit_xml(self): ], "testRunner": "raw", "group": "", - "noBuild": False, - "flavors": [], - "testSuite": "", }) @responses.activate diff --git a/tests/test_session.py b/tests/test_session.py index a1d1c578c..c01a5235f 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -1,42 +1,13 @@ -import os -import shutil -import tempfile from unittest import TestCase from launchable.utils.exceptions import ParseSessionException -from launchable.utils.session import (SESSION_DIR_KEY, clean_session_files, parse_session, read_build, read_session, - remove_session, validate_session_format, write_build, write_session) +from launchable.utils.session import parse_session, validate_session_format class SessionTestClass(TestCase): build_name = '123' session_id = '/intake/organizations/launchableinc/workspaces/mothership/builds/123/test_sessions/13' - def setUp(self): - self.dir = tempfile.mkdtemp() - os.environ[SESSION_DIR_KEY] = self.dir - - def tearDown(self): - clean_session_files() - del os.environ[SESSION_DIR_KEY] - shutil.rmtree(self.dir) - - def test_write_read_build(self): - self.assertEqual(read_build(), None) - write_build(self.build_name) - self.assertEqual(read_build(), self.build_name) - - def test_write_read_remove_session(self): - write_build(self.build_name) - write_session(self.build_name, self.session_id) - self.assertEqual(read_session(self.build_name), self.session_id) - - remove_session() - self.assertEqual(read_session(self.build_name), None) - - def test_read_before_write(self): - self.assertEqual(read_session(self.build_name), None) - def test_parse_session(self): session = "builds/build-name/test_sessions/123" build_name, session_id = parse_session(session) diff --git a/tests/utils/test_fail_fast_mode.py b/tests/utils/test_fail_fast_mode.py index c150e5f8f..a0e251bf5 100644 --- a/tests/utils/test_fail_fast_mode.py +++ b/tests/utils/test_fail_fast_mode.py @@ -1,31 +1,4 @@ -import io -from contextlib import contextmanager, redirect_stderr - -from launchable.utils.commands import Command -from launchable.utils.fail_fast_mode import FailFastModeValidateParams, fail_fast_mode_validate -from tests.cli_test_case import CliTestCase - - -class FailFastModeTest(CliTestCase): - def test_fail_fast_mode_validate(self): - params = FailFastModeValidateParams( - command=Command.SUBSET, - session='session1', - test_suite='test_suite1', - is_observation=True, - ) - stderr = io.StringIO() - - with self.assertRaises(SystemExit) as cm: - with tmp_set_fail_fast_mode(False), redirect_stderr(stderr): - # `--observation` option won't be applied but the cli won't be error - fail_fast_mode_validate(params) - self.assertEqual(stderr.getvalue(), "") - - with tmp_set_fail_fast_mode(True), redirect_stderr(stderr): - fail_fast_mode_validate(params) - self.assertEqual(cm.exception.code, 1) - self.assertIn("ignored", stderr.getvalue()) +from contextlib import contextmanager @contextmanager