Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Add initial tests for the Remote client plugin #22527

Merged
merged 30 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c7984cc
feat: add tests for remote client ipythonconsole integration and plugin
hlouzada Sep 18, 2024
caa4831
fix: add missing pytest-docker requirement
hlouzada Sep 18, 2024
255c697
fix: add workflow for remote-client and separate from regular tests
hlouzada Sep 25, 2024
cc888de
fix: update wrong remoteclient workflow tests name
hlouzada Sep 25, 2024
67dbcee
fix: update typings for python 3.8 compatibility
hlouzada Sep 25, 2024
6554d9e
fix: wrong remoteclient plugin path
hlouzada Sep 25, 2024
bde70f8
fix: add annotations import for typings
hlouzada Sep 25, 2024
1db948d
fix: call pytest directly in workflow
hlouzada Sep 25, 2024
47db611
fix: typo on pytest argument with remote client tests workflow
hlouzada Sep 25, 2024
0380a6b
add pytest-docker requirement to binder
hlouzada Sep 30, 2024
6add659
fix: remove pytest-docker from dependencies and install it in install.sh
hlouzada Sep 30, 2024
b1b1611
Apply suggestions from code review
hlouzada Sep 30, 2024
c8fc1f7
fix: set micromamba version to conda env test
hlouzada Sep 30, 2024
4440f87
fix: use xvfb-run in remoteclient tests
hlouzada Sep 30, 2024
8965845
fix: use run_test script to start remoteclient tests
hlouzada Sep 30, 2024
7a7eb60
fix: start docker daemon in remoteclient test enviroment
hlouzada Sep 30, 2024
b33d499
fix: install dependencies and spyder in remoteclient tests
hlouzada Sep 30, 2024
676d350
fix: wrong variable name in running_remoteclient_tests
hlouzada Sep 30, 2024
3191a43
fix: docker and docker-compose already installed in github images
hlouzada Sep 30, 2024
af4a6ec
feat: add flaky to rerun tests for installation and container build t…
hlouzada Sep 30, 2024
a1dc91a
Testing: Don't split test suite for remote client tests
ccordoba12 Sep 30, 2024
dd89fc7
feat: set one docker per class
hlouzada Sep 30, 2024
0ad7196
Revert "feat: set one docker per class"
hlouzada Sep 30, 2024
c44f8ab
fix: ignore last_activity from kernel info
hlouzada Sep 30, 2024
e8b147b
fix: apply revisions
hlouzada Oct 5, 2024
3ed4d96
feat: add new shell fixture and set class fixture for kernels
hlouzada Oct 6, 2024
218bee9
feat: add test class and test for kernel interrupts
hlouzada Oct 6, 2024
525a049
Apply suggestions from code review
hlouzada Oct 6, 2024
31441a0
fix: pep8
hlouzada Oct 6, 2024
e5e01d9
Merge branch 'master' into feat-remoteclient-tests
ccordoba12 Oct 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 30 additions & 25 deletions .github/scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,35 +64,40 @@ fi
# Install subrepos from source
python -bb -X dev install_dev_repos.py --not-editable --no-install spyder

# Install boilerplate plugin
pushd spyder/app/tests/spyder-boilerplate
pip install --no-deps -q -e .
popd

# Install Spyder to test it as if it was properly installed.
python -bb -X dev -m build
python -bb -X dev -m pip install --no-deps dist/spyder*.whl

# Adjust PATH on Windows so that we can use conda below. This needs to be done
# at this point or the pip slots fail.
if [ "$OS" = "win" ]; then
PATH=/c/Miniconda/Scripts/:$PATH
fi
if [ "$SPYDER_TEST_REMOTE_CLIENT" = "true" ]; then
pip install pytest-docker
else

# Install boilerplate plugin
pushd spyder/app/tests/spyder-boilerplate
pip install --no-deps -q -e .
popd

# Adjust PATH on Windows so that we can use conda below. This needs to be done
# at this point or the pip slots fail.
if [ "$OS" = "win" ]; then
PATH=/c/Miniconda/Scripts/:$PATH
fi

# Create environment for Jedi environment tests
conda create -n jedi-test-env -q -y python=3.9 flask
install_spyder_kernels jedi-test-env
conda list -n jedi-test-env

# Create environment to test conda env activation before launching a kernel
conda create -n spytest-ž -q -y -c conda-forge python=3.9
install_spyder_kernels spytest-ž
conda list -n spytest-ž

# Install pyenv on Linux systems
if [ "$RUN_SLOW" = "false" ]; then
if [ "$OS" = "linux" ]; then
curl https://pyenv.run | bash
$HOME/.pyenv/bin/pyenv install 3.8.1
# Create environment for Jedi environment tests
conda create -n jedi-test-env -q -y python=3.9 flask
install_spyder_kernels jedi-test-env
conda list -n jedi-test-env

# Create environment to test conda env activation before launching a kernel
conda create -n spytest-ž -q -y -c conda-forge python=3.9
install_spyder_kernels spytest-ž
conda list -n spytest-ž

# Install pyenv on Linux systems
if [ "$RUN_SLOW" = "false" ]; then
if [ "$OS" = "linux" ]; then
curl https://pyenv.run | bash
$HOME/.pyenv/bin/pyenv install 3.8.1
fi
fi
fi
10 changes: 7 additions & 3 deletions .github/scripts/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ else
fi

# Run tests
if [ "$OS" = "linux" ]; then
xvfb-run --auto-servernum python runtests.py --color=yes | tee -a pytest_log.txt
if [ "$SPYDER_TEST_REMOTE_CLIENT" = "true" ]; then
xvfb-run --auto-servernum python runtests.py --color=yes --remote-client | tee -a pytest_log.txt
else
python runtests.py --color=yes | tee -a pytest_log.txt
if [ "$OS" = "linux" ]; then
xvfb-run --auto-servernum python runtests.py --color=yes | tee -a pytest_log.txt
else
python runtests.py --color=yes | tee -a pytest_log.txt
fi
fi
160 changes: 160 additions & 0 deletions .github/workflows/test-remoteclient.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
name: Remote Client Tests

on:
push:
branches:
- master
- 6.*
paths:
- '.github/scripts/*.sh'
- '.github/workflows/*.yml'
- 'requirements/*.yml'
- '**.bat'
- '**.py'
- '**.sh'
- '!installers-conda/**'
- '!.github/workflows/installers-conda.yml'
- '!.github/workflows/build-subrepos.yml'

pull_request:
branches:
- master
- 6.*
paths:
- '.github/scripts/*.sh'
- '.github/workflows/*.yml'
- 'requirements/*.yml'
- '**.bat'
- '**.py'
- '**.sh'
- '!installers-conda/**'
- '!.github/workflows/installers-conda.yml'
- '!.github/workflows/build-subrepos.yml'

workflow_dispatch:
inputs:
ssh:
# github_cli: gh workflow run test-linux.yml --ref <branch> -f ssh=true
description: 'Enable ssh debugging'
required: false
default: false
type: boolean

concurrency:
group: test-remoteclient-${{ github.ref }}
cancel-in-progress: true

env:
ENABLE_SSH: ${{ github.event_name == 'workflow_dispatch' && inputs.ssh }}

jobs:
build:
# Use this to disable the workflow
# if: false
name: Linux - Py${{ matrix.PYTHON_VERSION }}, ${{ matrix.INSTALL_TYPE }}
runs-on: ubuntu-20.04
env:
CI: 'true'
QTCONSOLE_TESTING: 'true'
CODECOV_TOKEN: "56731c25-9b1f-4340-8b58-35739bfbc52d"
OS: 'linux'
PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }}
USE_CONDA: ${{ matrix.INSTALL_TYPE == 'conda' }}
SPYDER_TEST_REMOTE_CLIENT: 'true'
strategy:
fail-fast: false
matrix:
INSTALL_TYPE: ['pip', 'conda']
PYTHON_VERSION: ['3.8', '3.12']
exclude:
# Only test Python 3.8 with pip because Conda-forge will drop it soon
- INSTALL_TYPE: 'conda'
PYTHON_VERSION: '3.8'
timeout-minutes: 90
steps:
- name: Setup Remote SSH Connection
if: env.ENABLE_SSH == 'true'
uses: mxschmitt/action-tmate@v3
timeout-minutes: 60
with:
detached: true
- name: Checkout Pull Requests
if: github.event_name == 'pull_request'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout Push
if: github.event_name != 'pull_request'
uses: actions/checkout@v4
- name: Fetch branches
run: git fetch --prune --unshallow
- name: Install dependencies
shell: bash
run: |
sudo apt-get update --fix-missing
sudo apt-get install -qq pyqt5-dev-tools libxcb-xinerama0 xterm --fix-missing
- name: Cache conda
uses: actions/cache@v4
env:
# Increase this value to reset cache if requirements/*.txt has not changed
CACHE_NUMBER: 0
with:
path: ~/conda_pkgs_dir
key: ${{ runner.os }}-cacheconda-install${{ matrix.INSTALL_TYPE }}-${{ matrix.PYTHON_VERSION }}-${{ env.CACHE_NUMBER }}-${{ hashFiles('requirements/*.yml') }}
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-cachepip-install${{ matrix.INSTALL_TYPE }}-${{ env.CACHE_NUMBER }}-${{ hashFiles('setup.py') }}
- name: Create conda test environment
if: env.USE_CONDA == 'true'
uses: mamba-org/setup-micromamba@v1
with:
micromamba-version: '1.5.10-0'
environment-file: requirements/main.yml
hlouzada marked this conversation as resolved.
Show resolved Hide resolved
environment-name: test
cache-downloads: true
create-args: python=${{ matrix.PYTHON_VERSION }}
- name: Create pip test environment
if: env.USE_CONDA != 'true'
uses: mamba-org/setup-micromamba@v1
with:
micromamba-version: '1.5.10-0'
environment-name: test
hlouzada marked this conversation as resolved.
Show resolved Hide resolved
cache-downloads: true
create-args: python=${{ matrix.PYTHON_VERSION }}
condarc: |
channels:
- conda-forge
- name: Install additional dependencies
shell: bash -l {0}
run: bash -l .github/scripts/install.sh
- name: Show conda test environment
if: env.USE_CONDA == 'true'
shell: bash -l {0}
run: |
micromamba info
micromamba list
- name: Show pip test environment
if: env.USE_CONDA != 'true'
shell: bash -l {0}
run: |
micromamba info
micromamba list
pip list
- name: Run tests
shell: bash -l {0}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
rm -f pytest_log.txt
rm -f pytest_log.txt # Must remove any log file from a previous run
.github/scripts/run_tests.sh || \
.github/scripts/run_tests.sh || \
.github/scripts/run_tests.sh || \
.github/scripts/run_tests.sh
- name: Coverage
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: false
verbose: true
4 changes: 3 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ def pytest_collection_modifyitems(config, items):
# This provides a more balanced partitioning of our test suite (in terms of
# necessary time to run it) between the slow and fast slots we have on CIs.
slow_items = []
if os.environ.get('CI'):
if os.environ.get("CI") and not os.environ.get(
"SPYDER_TEST_REMOTE_CLIENT"
):
slow_items = [
item for item in items if 'test_mainwindow' in item.nodeid
]
Expand Down
19 changes: 15 additions & 4 deletions runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
RUN_SLOW = os.environ.get('RUN_SLOW', None) == 'true'


def run_pytest(run_slow=False, extra_args=None):
def run_pytest(run_slow=False, extra_args=None, remoteclient=False):
"""Run pytest tests for Spyder."""
# Be sure to ignore subrepos
# Be sure to ignore subrepos and remoteclient plugin
pytest_args = ['-vv', '-rw', '--durations=10', '--ignore=./external-deps',
'-W ignore::UserWarning', '--timeout=120',
'--timeout_method=thread']
Expand All @@ -49,6 +49,13 @@ def run_pytest(run_slow=False, extra_args=None):
if extra_args:
pytest_args += extra_args

if remoteclient:
pytest_args += ['--container-scope=class',
'./spyder/plugins/remoteclient']
os.environ["SPYDER_TEST_REMOTE_CLIENT"] = "true"
else:
pytest_args += ['--ignore=./spyder/plugins/remoteclient']

print("Pytest Arguments: " + str(pytest_args))
errno = pytest.main(pytest_args)

Expand All @@ -62,12 +69,16 @@ def run_pytest(run_slow=False, extra_args=None):
def main():
"""Parse args then run the pytest suite for Spyder."""
test_parser = argparse.ArgumentParser(
usage='python runtests.py [-h] [--run-slow] [pytest_args]',
usage=('python runtests.py'
'[-h] [--run-slow] [--remote-client] [pytest_args]'),
description="Helper script to run Spyder's test suite")
test_parser.add_argument('--run-slow', action='store_true', default=False,
help='Run the slow tests')
test_parser.add_argument("--remote-client", action="store_true",
default=False, help="Run the remote client tests")
test_args, pytest_args = test_parser.parse_known_args()
run_pytest(run_slow=test_args.run_slow, extra_args=pytest_args)
run_pytest(run_slow=test_args.run_slow, extra_args=pytest_args,
remoteclient=test_args.remote_client)


if __name__ == '__main__':
Expand Down
10 changes: 10 additions & 0 deletions spyder/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ def running_under_pytest():
return bool(os.environ.get('SPYDER_PYTEST'))


def running_remoteclient_tests():
hlouzada marked this conversation as resolved.
Show resolved Hide resolved
"""
Return True if currently running the remoteclient tests.

This function is used to do some adjustment for testing. The environment
variable SPYDER_TEST_REMOTE_CLIENT is 'true' in conftest.py.
"""
return bool(os.environ.get("SPYDER_TEST_REMOTE_CLIENT") == "true")
hlouzada marked this conversation as resolved.
Show resolved Hide resolved


def running_in_ci():
"""Return True if currently running under CI."""
return bool(os.environ.get('CI'))
Expand Down
7 changes: 5 additions & 2 deletions spyder/plugins/ipythonconsole/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@
IPython Console plugin based on QtConsole
"""

from spyder.config.base import is_stable_version
from spyder.config.base import is_stable_version, running_remoteclient_tests


# Use this variable, which corresponds to the html dash symbol, for any command
# that requires a dash below. That way users will be able to copy/paste
# commands from the kernel error message directly to their terminals.
_d = '&#45;'

# Required version of Spyder-kernels
SPYDER_KERNELS_MIN_VERSION = '3.1.0.dev0'
SPYDER_KERNELS_MIN_VERSION = (
"3.0.0" if running_remoteclient_tests() else "3.1.0.dev0"
)
SPYDER_KERNELS_MAX_VERSION = '3.2.0'
SPYDER_KERNELS_VERSION = (
f'>={SPYDER_KERNELS_MIN_VERSION},<{SPYDER_KERNELS_MAX_VERSION}'
Expand Down
37 changes: 37 additions & 0 deletions spyder/plugins/remoteclient/tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
FROM ubuntu:focal AS ubuntu-base
ENV DEBIAN_FRONTEND noninteractive
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Setup the default user.
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo ubuntu
RUN echo 'ubuntu:ubuntu' | chpasswd

# Install required tools.
RUN apt-get -qq update \
&& apt-get -qq --no-install-recommends install curl \
&& apt-get -qq --no-install-recommends install ca-certificates \
&& apt-get -qq --no-install-recommends install vim-tiny \
&& apt-get -qq --no-install-recommends install sudo \
&& apt-get -qq --no-install-recommends install openssh-server \
&& apt-get -qq clean \
&& rm -rf /var/lib/apt/lists/*

# Configure SSHD.
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
RUN mkdir /var/run/sshd
RUN bash -c 'install -m755 <(printf "#!/bin/sh\nexit 0") /usr/sbin/policy-rc.d'
RUN ex +'%s/^#\zeListenAddress/\1/g' -scwq /etc/ssh/sshd_config
RUN ex +'%s/^#\zeHostKey .*ssh_host_.*_key/\1/g' -scwq /etc/ssh/sshd_config
RUN RUNLEVEL=1 dpkg-reconfigure openssh-server
RUN ssh-keygen -A -v
RUN update-rc.d ssh defaults

# Configure sudo.
RUN ex +"%s/^%sudo.*$/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/g" -scwq! /etc/sudoers

# Generate and configure user keys.
USER ubuntu
RUN ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519

CMD ["/usr/bin/sudo", "/usr/sbin/sshd", "-D", "-o", "ListenAddress=172.16.128.2"]
7 changes: 7 additions & 0 deletions spyder/plugins/remoteclient/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)

"""Spyder Remote Client Tests"""
Loading
Loading