Skip to content

Commit

Permalink
test: add behave & unit tests for run_extra_commands command
Browse files Browse the repository at this point in the history
* refactor: solve some linter issues and
  • Loading branch information
bra-i-am committed Apr 1, 2024
1 parent 346e3c7 commit a1e3e4e
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 19 deletions.
14 changes: 14 additions & 0 deletions features/run_extra_commands.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Feature: Run extra commands
@fixture.behave.tutor_root
Scenario: Execute the extra commands from config.yml properly
Given There is a tutor root
And There is a config.yml file
And There are valid commands defined
When I write the command tutor distro run-extra-commands and commands will be properly executed

@fixture.behave.tutor_root
Scenario: Execute commands that are not valid
Given There is a tutor root
And There is a config.yml file
And There are invalid commands defined
When I write the command tutor distro run-extra-commands and commands execution will fail
64 changes: 64 additions & 0 deletions features/steps/run_extra_commands_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os

import subprocess

from behave import given, when, then # pylint: disable=no-name-in-module
from click.testing import CliRunner
from tutor import config as tutor_config

from tutordistro.commands.run_extra_commands import run_extra_commands


@given("There are valid commands defined")
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring
extra_commands = [
"tutor plugins update",
"tutor plugins install forum",
"tutor plugins enable forum"
]

config = context.scenario.config
config.update({
"DISTRO_EXTRA_COMMANDS": extra_commands
})

tutor_config.save_config_file(context.scenario.tutor_root, config)
config = tutor_config.load(context.scenario.tutor_root)
context.scenario.config = config
context.scenario.extra_commands = "DISTRO_EXTRA_COMMANDS"

assert "DISTRO_EXTRA_COMMANDS" in config


@given("There are invalid commands defined")
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring
extra_commands = [
"pip install application"
]

config = context.scenario.config
config.update({
"DISTRO_EXTRA_COMMANDS": extra_commands
})

tutor_config.save_config_file(context.scenario.tutor_root, config)
config = tutor_config.load(context.scenario.tutor_root)
context.scenario.config = config
context.scenario.extra_commands = "DISTRO_EXTRA_COMMANDS"

assert "DISTRO_EXTRA_COMMANDS" in config


@when("I write the command tutor distro run-extra-commands and commands will be properly executed")
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring
runner = CliRunner()
result = runner.invoke(run_extra_commands, obj=context)
assert result.exit_code == 0


@when("I write the command tutor distro run-extra-commands and commands execution will fail")
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring
runner = CliRunner()
result = runner.invoke(run_extra_commands, obj=context)
assert result.exit_code != 0

Empty file.
Empty file.
74 changes: 74 additions & 0 deletions tests/distro/run_extra_commands/application/test_run_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Test run commands application.
"""

import pytest

from tests.distro.run_extra_commands.infrastructure.test_tutor_commands import TestTutorCommandManager
from tutordistro.distro.extra_commands.application.commands_runner import CommandsRunner
from tutordistro.distro.share.domain.command_error import CommandError


def test_valid_tutor_command():
"""
Test running valid commands.
This test verifies that are executed all the extra commands successfully.
"""
# Given
tutor_commands_manager = TestTutorCommandManager()
run_tutor_command = CommandsRunner(commands_manager=tutor_commands_manager)

valid_tutor_commands = [
"command with word tutor 1",
"command with word tutor 2",
"command with word tutor 3",
]

# When
for command in valid_tutor_commands:
run_tutor_command(command=command)

assert tutor_commands_manager.commands_ran == len(valid_tutor_commands)


def test_invalid_tutor_command():
"""
Test running invalid commands.
This test verifies that the execution fails when is
intended to execute invalid extra commands.
"""
# Given
tutor_commands_manager = TestTutorCommandManager()
run_tutor_command = CommandsRunner(commands_manager=tutor_commands_manager)

invalid_tutor_command = "pip command 1"

# When
with pytest.raises(CommandError) as command_error:
run_tutor_command(command=invalid_tutor_command)

assert command_error.type is CommandError
assert "is not a valid Tutor command" in command_error.value.args[0]


def test_misspelled_tutor_command():
"""
Test running misspelled Tutor commands.
This test verifies that is warned the user of trying to execute
a misspelled Tutor command.
"""
# Given
tutor_commands_manager = TestTutorCommandManager()
run_tutor_command = CommandsRunner(commands_manager=tutor_commands_manager)

invalid_tutor_command = "totur command bad written"

# When
with pytest.raises(CommandError) as command_error:
run_tutor_command(command=invalid_tutor_command)

assert command_error.type is CommandError
assert "you have a typo" in command_error.value.args[0]
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
Test tutor commands functions.
"""

from tutordistro.distro.extra_commands.domain.command_manager import CommandManager
from tutordistro.distro.share.domain.command_error import CommandError
from tutordistro.utils.constants import find_tutor_misspelled


class TestTutorCommandManager(CommandManager):
"""
Executes a Tutor command for testing.
This class provides functionality to execute extra Tutor commands for testing.
Args:
CommandManager (class): Base command manager class.
"""
commands_ran = 0

def run_command(self, command: str):
"""
This method runs an testing command.
Args:
command (str): Testing command.
"""
is_tutor_misspelled = find_tutor_misspelled(command)

if "tutor" not in command.lower():
if is_tutor_misspelled:
raise CommandError(
f'Maybe you have a typo using the command "{command}"'
)
raise CommandError(
f'''
Command "{command}" is not a valid Tutor command.
Take the official Tutor commands into account
https://docs.tutor.edly.io/reference/cli/index.html
'''
)
self.commands_ran += 1
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ class CommandManager(metaclass=abc.ABCMeta):
"""Command Manager"""

@abstractmethod
def run_command(self, command: str, tutor_root: str):
def run_command(self, command: str):
"""Run a command."""
45 changes: 27 additions & 18 deletions tutordistro/distro/extra_commands/infrastructure/tutor_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
Distro tutor commands functions.
"""

import os
import subprocess
import re

from tutordistro.distro.extra_commands.domain.command_manager import CommandManager
from tutordistro.distro.share.domain.command_error import CommandError
from tutordistro.utils.constants import find_tutor_misspelled


class TutorCommandManager(CommandManager):
Expand All @@ -28,26 +27,36 @@ def run_command(self, command: str):
Args:
command (str): Tutor command.
tutor_root (str): Tutor path where to execute the command.
"""
try:
is_tutor_bad_written = re.match(r'[tT](?:[oru]{3}|[oru]{2}[rR]|[oru]u?)', command)
is_tutor_misspelled = find_tutor_misspelled(command)

if "tutor" not in command.lower():
if is_tutor_bad_written:
raise CommandError(f'Maybe you have a typo using the command "{command}"')
else:
raise CommandError(f'Command "{command}" is not a valid Tutor command. Take the official Tutor commands into account https://docs.tutor.edly.io/reference/cli/index.html')

process = subprocess.Popen(
if is_tutor_misspelled:
raise CommandError(
f'Maybe you have a typo using the command "{command}"'
)
raise CommandError(
f"""
Command "{command}" is not a valid Tutor command.
Take the official Tutor commands into account
https://docs.tutor.edly.io/reference/cli/index.html
"""
)
with subprocess.Popen(
command,
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/bash'
)

output, error = process.communicate()
# If a command failed
if process.returncode != 0:
raise CommandError(f'Error running command "{command}".\n{output.decode()}\n{error.decode()}')
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
executable="/bin/bash",
) as process:
output, error = process.communicate()
# If a command failed
if process.returncode != 0:
raise CommandError(
f'Error running command "{command}".\n{error.decode()}'
)
print(output.decode())

except subprocess.SubprocessError as error:
raise CommandError(f'Error running command {command}: {error}') from error
raise CommandError(f"Error running command {command}: {error}") from error
17 changes: 17 additions & 0 deletions tutordistro/utils/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
File of constant variables
"""
import re


def find_tutor_misspelled(command: str):
"""
This function takes a command and looks if it has the word 'tutor' misspelled
Args:
command (str): Command to be reviewed
Return:
If its found the word 'tutor' misspelled is returned True
"""
return re.match(r'[tT](?:[oru]{3}|[oru]{2}[rR]|[oru]u?)', command)

0 comments on commit a1e3e4e

Please sign in to comment.