diff --git a/.github/actions/install-pkg/action.yml b/.github/actions/install-pkg/action.yml deleted file mode 100644 index 4b4e2d92..00000000 --- a/.github/actions/install-pkg/action.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Install earthaccess Python package -description: Install earthaccess Python package and testing dependencies - -inputs: - python-version: - description: Version of Python to use - required: true - -runs: - using: composite - steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ inputs.python-version }} - cache: pip - - - name: Display full python version - shell: bash - id: full-python-version - run: echo "version=$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")" >> $GITHUB_OUTPUT - - - name: Install package and test dependencies - shell: bash - run: pip install --root-user-action ignore ".[test]" diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 62c1043a..05e5bb2b 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -94,16 +94,16 @@ jobs: # this point. ref: ${{ github.event.pull_request.head.sha }} - - name: Install package with dependencies - uses: ./.github/actions/install-pkg + - name: Setup nox + uses: wntrblm/nox@2024.10.09 with: - python-version: ${{ matrix.python-version }} + python-versions: ${{ matrix.python-version }} - name: Run integration tests env: EARTHDATA_USERNAME: ${{ secrets.EDL_USERNAME }} EARTHDATA_PASSWORD: ${{ secrets.EDL_PASSWORD }} - run: ./scripts/integration-test.sh + run: nox -s integration-tests -- --cov=earthaccess --cov-report=term-missing --capture=no --tb=native --log-cli-level=INFO - name: Upload coverage report # Don't upload coverage when using the `act` tool to run the workflow locally diff --git a/.github/workflows/test-mindeps.yml b/.github/workflows/test-mindeps.yml index 3705c69b..f7de53d7 100644 --- a/.github/workflows/test-mindeps.yml +++ b/.github/workflows/test-mindeps.yml @@ -27,8 +27,8 @@ jobs: version: "0.4.7" enable-cache: true - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup nox + uses: wntrblm/nox@2024.10.09 with: python-version: 3.9 @@ -39,7 +39,7 @@ jobs: run: uv pip install --no-deps . - name: Test - run: uv run pytest tests/unit --cov=earthaccess --cov=tests --cov-report=term-missing --capture=no --tb=native --log-cli-level=INFO + run: nox -s test-min-deps -- --verbose --cov=earthaccess --cov-report=term-missing --capture=no --tb=native --log-cli-level=INFO - name: Upload coverage # Don't upload coverage when using the `act` tool to run the workflow locally diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cd7b6cd3..7bc6bde6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,15 +19,16 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - - uses: ./.github/actions/install-pkg + - name: Setup nox + uses: wntrblm/nox@2024.10.09 with: - python-version: ${{ matrix.python-version }} + python-versions: ${{ matrix.python-version }} - name: Typecheck - run: mypy + run: nox -s typecheck - name: Test - run: pytest tests/unit --verbose --cov=earthaccess --cov-report=term-missing --capture=no --tb=native --log-cli-level=INFO + run: nox -s tests -- --verbose --cov=earthaccess --cov-report=term-missing --capture=no --tb=native --log-cli-level=INFO - name: Upload coverage # Don't upload coverage when using the `act` tool to run the workflow locally diff --git a/noxfile.py b/noxfile.py index badf6bec..23341d2a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -27,27 +27,45 @@ def tests(session: nox.Session) -> None: session.run( "pytest", "tests/unit", - "-rxXs", # Show provided reason in summary for (x)fail, (X)pass, and (s)kipped statuses + "-rxXs", # Show provided reason in summary for (x)fail, (X)pass, and (s)kipped tests *session.posargs, ) +@nox.session(name="test-min-deps", python="3.9") +def test_min_deps(session: nox.Session) -> None: + """Run the unit tests.""" + session.install("--resolution", "lowest-direct", "--editable", ".[test]") + session.run( + "pytest", + "tests/unit", + "-rxXs", # Show provided reason in summary for (x)fail, (X)pass, and (s)kipped tests + *session.posargs, + ) + + @nox.session(name="integration-tests") def integration_tests(session: nox.Session) -> None: """Run the integration tests.""" session.install("--editable", ".[test]") session.run( - "scripts/integration-test.sh", + "pytest", + "tests/integration", + "-rxXs", # Show provided reason in summary for (x)fail, (X)pass, and (s)kipped tests *session.posargs, env=dict( EARTHDATA_USERNAME=os.environ["EARTHDATA_USERNAME"], EARTHDATA_PASSWORD=os.environ["EARTHDATA_PASSWORD"], ), external=True, + # NOTE: integration test are permitted to pass if the failure rate was less than a hardcoded threshold. + # PyTest will return 99 if there were some failures, but less than the threshold. For more details, see: + # `pytest_sessionfinish` in tests/integration/conftest.py + success_codes=[0, 99], ) -@nox.session +@nox.session(name="build-pkg") def build_pkg(session: nox.Session) -> None: """Build a source distribution and binary distribution (wheel).""" build_path = DIR.joinpath("build") @@ -58,7 +76,7 @@ def build_pkg(session: nox.Session) -> None: session.run("python", "-m", "build") -@nox.session +@nox.session(name="serve-docs") def serve_docs(session: nox.Session) -> None: """Build the documentation and serve it.""" session.install("--editable", ".[docs]") diff --git a/scripts/integration-test.sh b/scripts/integration-test.sh deleted file mode 100755 index 457e8469..00000000 --- a/scripts/integration-test.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -x -pytest tests/integration -rxXs --cov=earthaccess --cov-report=term-missing "${@}" --capture=no --tb=native --log-cli-level=INFO -RET=$? -set +x - -set -e -# NOTE: 99 is a special return code we selected for this case, it has no other meaning. -if [[ $RET == 99 ]]; then - echo -e "\e[0;31mWARNING: The integration test suite has been permitted to return 0 because the failure rate was less than a hardcoded threshold.\e[0m" - echo "For more details, see conftest.py." - exit 0 -elif [[ $RET != 0 ]]; then - exit $RET -fi diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 8c206885..6d702a50 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,5 +1,6 @@ import os import pathlib +from warnings import warn import earthaccess import pytest @@ -22,6 +23,9 @@ def pytest_sessionfinish(session, exitstatus): ratio will change depending on which tests are executed! E.g. executing integration tests and unit tests at the same time allows more tests to fail than executing integration tests alone. + + NOTE: The return exit code can be customized with the `EARTHACCESS_ALLOWABLE_FAILURE_STATUS_CODE` + environment variable. """ if exitstatus != pytest.ExitCode.TESTS_FAILED: # Exit status 1 in PyTest indicates "Tests were collected and run but some of @@ -30,9 +34,15 @@ def pytest_sessionfinish(session, exitstatus): # want to defer to original pytest behavior. return + failure_rate = (100.0 * session.testsfailed) / session.testscollected if failure_rate <= ACCEPTABLE_FAILURE_RATE: - session.exitstatus = 99 + warn( + '\nWARNING: The integration test suite has been allowed to pass because the ' + 'failure rate was less than a hardcoded threshold. For more details see:\n' + 'tests/integration/conftest.py.' + ) + session.exitstatus = os.environ.get('EARTHACCESS_ALLOWABLE_FAILURE_STATUS_CODE', 99) @pytest.fixture