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

Container Support #30

Open
hennevogel opened this issue Oct 25, 2019 · 4 comments
Open

Container Support #30

hennevogel opened this issue Oct 25, 2019 · 4 comments
Labels
bug Something isn't working

Comments

@hennevogel
Copy link

Your environment

  • vscode-ruby-test-adapter version: 0.6.0
  • Ruby version: 2.5.7
  • VS Code version: 1.39.2
  • Operating System: Linux
  • RSpec version: 3.9.0

Expected behavior

My development environment uses containers so I set rubyTestExplorer.rspecCommand to something like docker-compose run --rm frontend bundle exec rspec and the vscode-ruby-test-adapter works

Actual behavior

There are a couple of problems with this:

  1. Somehow the CustomFormatter needs to get into my container. This can be work arounded by making getCustomFormatterLocation configurable and putting the file into the workspace somehow (like copy it to .vscode/custom_formatter.rb)
  2. Inside the container the files will not be in the same absolute path than the workspace is. So rubyTestExplorer.*Directory somehow needs to be not relative to the workspace.
@hennevogel hennevogel added the bug Something isn't working label Oct 25, 2019
@jirikivaari
Copy link

jirikivaari commented Mar 21, 2020

@hennevogel, I fixed this by copying this file to docker container but it makes the plugin work only partially. You can run tests once but not one single of them. There is some other issue.

I would like to have this feature too without even speciying any commands. Like [x] Docker.

@mstate
Copy link

mstate commented Jan 18, 2022

I got this working by configuring test explorer to use a shell script as my rspec command.

Contents of rspec-inside-docker.sh

#!/bin/bash

MY_MODIFIED_RSPEC=$(echo $@ | sed -r "s#[A-Za-z0-9_/\-]+spec/#spec/#g")
COMPOSE_SERVICE_NAME=app
echo "Running Command:"
echo docker compose exec -e RAILS_ENV=test -T $COMPOSE_SERVICE_NAME sh -c "bundle exec rspec ${MY_MODIFIED_RSPEC}"
docker compose exec -e RAILS_ENV=test -T $COMPOSE_SERVICE_NAME sh -c "bundle exec rspec ${MY_MODIFIED_RSPEC}"

@Splines

This comment was marked as outdated.

@Splines
Copy link

Splines commented Dec 15, 2023

I couldn't find a good solution for this, so I wrote my own custom script to finally achieve this. Use it however you like in your project. Of course, you will have to tweak the script to make it work in your environment.

💫 Python Script: rspec_inside_docker.py
# call this file: rspec_inside_docker.py
# and put it in your ./spec/ folder

# Specify the following (or alike) in your settings.json
# "rubyTestExplorer.testFramework": "rspec",
# "rubyTestExplorer.rspecCommand": "python3 ./spec/rspec_inside_docker.py",
# "rubyTestExplorer.rspecDirectory": "./spec/",
# "rubyTestExplorer.logpanel": true,
# "rubyTestExplorer.filePattern": ["*_spec.rb"],

import sys
import subprocess

# Path where the custom formatter of the Ruby Test explorer extension is memory-mapped
FORMATTER_PATH_IN_DOCKER = "/root/tmp/formatter.rb"
PROJECT_ROOT_FOLDER_NAME = "mampf"
DOCKER_SERVICE_NAME = "mampf"


def switch_formatter_path():
    """
    Memory-maps the custom formatter of the Ruby Test explorer extension.

    The Ruby Test explorer extension uses a custom formatter to get a specific
    output JSON format. The path to the formatter is automatically passed as an
    argument to the rspec command by the extension. We need to replace this
    path by the path to the memory-mapped formatter in the Docker container.
    """

    formatter_argument_index = None
    for i, arg in enumerate(sys.argv):
        if arg == '--require':
            formatter_argument_index = i
            break

    if formatter_argument_index == None:
        print('Please specify "--require path/to/custom/formatter.rb"')
        sys.exit(1)

    # Switch the path to the custom formatter to the memory-mapped path
    formatter_path_on_host = sys.argv[formatter_argument_index + 1]
    sys.argv[formatter_argument_index + 1] = FORMATTER_PATH_IN_DOCKER

    return formatter_path_on_host


def process_paths():
    for i, arg in enumerate(sys.argv):
        if not arg.startswith('./') and "spec" in arg:
            sys.argv[i] = replace_absolute_paths_by_relative_paths(sys.argv[i])


def replace_absolute_paths_by_relative_paths(path):
    res = path.split(PROJECT_ROOT_FOLDER_NAME + '/')[1]
    if not res:
        print(f'Path {path}'
              f' does not contain string "{PROJECT_ROOT_FOLDER_NAME}/"')
        sys.exit(1)
    return './' + res  # make path relative


if __name__ == '__main__':
    formatter_path_on_host = switch_formatter_path()
    process_paths()

    rspec_args = ' '.join(sys.argv[1:])
    test_command = f'rake db:create db:migrate db:test:prepare && RAILS_ENV=test bundle exec rspec {rspec_args}'

    docker_cmd = f'cd ./docker/development && docker compose run -T --rm --entrypoint="" -v {formatter_path_on_host}:{FORMATTER_PATH_IN_DOCKER} {DOCKER_SERVICE_NAME} sh -c "{test_command}"'

    subprocess.call(docker_cmd, shell=True)

Sample output (VSCode connected to WSL2)

image

Current limitations

Creates a new docker container for every file to test. And in every docker container the test database has to be prepared, so tests take a long time to run through right now. Will have to figure out how to have all tests run in just one Docker container. Edit: I think that's not possible since it's the extension that executes our custom script for every file individually. A way to solve this is to create a docker environment just for testing that has the test database prepopulated so that we don't have to execute db:test:prepare each time a new container is spun up.

Edit: Solution for that limitation. If you use Run all tests in the VSCode test panel, only one docker container will be created which significantly reduces the time needed for all tests to run through.

Edit: I forgot to mention: in our setup, we have mounted the spec/ folder in the docker compose file in the volume section. That's why the relative paths in the python script are working out nicely.

Splines added a commit to MaMpf-HD/mampf that referenced this issue Dec 18, 2023
This builds on the Ruby Test Explorer VSCode extension.
See my comment here: connorshea/vscode-ruby-test-adapter#30 (comment)
Splines added a commit to MaMpf-HD/mampf that referenced this issue May 13, 2024
* Add Python script to run Rspec tests in docker container

This builds on the Ruby Test Explorer VSCode extension.
See my comment here: connorshea/vscode-ruby-test-adapter#30 (comment)

* Add Ruby Test explorer settings to `settings.json`

* Rename `run_cypress_tests` to `test` & use buildx

buildx is used for faster builds
we also set up ghcr to use docker layer caching for hopefully even
faster build times

* Fix paths to files and rename to `Testing`

* Use lowercase github org name

* Use GitHub Rspec formatter

* Clean up tests.yml & add comment with useful links

* Delete unnecessary dotfiles

* Fix path due to renaming of `run_cypress_tests` to `test`

* Add more comments to tests.yml

* Don't deal with cypress_runner here

* Only cache real build targets

Other layers will get cached anyways as they are external images.

* Source dummy docker env variables

* Add missing `require "rails_helper" statement

* Move comment to correct place in test

* Fix missing `=` in workflow file

* Source docker-dummy.env in docker test environment

* Don't source dummy docker env & add missing env variables

We just add the missing env variables to the docker-compose.yml config
for the test setup.

* Disable "can destroy users" test

* Copy missing app folder in Dockerfile (test setup)

* Remove creation of test database in workflow

* Precompile webpacker assets into docker test image

* Fix failing media search tests (first iteration)

* Fix media search tests

These changes are necessary due to #593.

* Upgrade Node.js dev dependencies

* Fix wrong ESLint semicolon-key value

* Remove pending test

* Freeze string assigned to constant (rubocop)

* Try to use `delete_all` instead of `destroy_all`

This may be a fix for the issue `Can't modify frozen hash` we get in the
pipeline during the unit tests.

* Don't delete Medium table as DatabaseClenaer takes care of it

* Improve database cleaner config according to docs

* Only rely on active record database cleaner gem

See the gem setup here:
https://www.rubydoc.info/github/DatabaseCleaner/database_cleaner#gem-setup

* Use before() & after() instead of around() in DB cleaner

* Explicitly require database_cleaner gem

* Use append_after() instead of append()

See here: https://www.rubydoc.info/github/DatabaseCleaner/database_cleaner#rspec-with-capybara-example

* Change directory to test folder

* Revert "Change directory to test folder"

This reverts commit ebbe53d.

* Try to use transactional fixtures

* Use database cleaner, omit before :all (instead use before :each)

* Pass token to Codecov test workflow

* Ignore test files in Codecov report

* Use testing GitHub environment for CI/CD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants