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

Unittest does not run properly #100

Closed
tomraulet opened this issue Jan 27, 2020 · 5 comments
Closed

Unittest does not run properly #100

tomraulet opened this issue Jan 27, 2020 · 5 comments

Comments

@tomraulet
Copy link

Hi there,

First, thank you for your package ;)

I'm unfortunately running on an issue. I've written unit tests, and trying to run them, I'm getting this error :

python -m unittest discover -s tests -p "*_tests.py"
usage: python -m unittest [-h] [--name NAME] [--log-level LOG_LEVEL]
                          [--log-format {json,pretty}] [--log-file LOG_FILE]
                          [--quiet]
                          [--metric-grouping-interval METRIC_GROUPING_INTERVAL]
                          [--debug] [--minimal]
                          {run} ...
python -m unittest: error: argument commands: invalid choice: 'discover' (choose from 'run')
E
======================================================================
ERROR: test_MY_SCRIPT_MY_FUNCTION (MY_SCRIPT_tests.MYSCRIPTSTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1787, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1975, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1952, in consume_positionals
    take_action(action, args)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1845, in take_action
    argument_values = self._get_values(action, argument_strings)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 2386, in _get_values
    self._check_value(action, value[0])
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 2433, in _check_value
    raise ArgumentError(action, msg % args)
argparse.ArgumentError: argument commands: invalid choice: 'discover' (choose from 'run')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/my/home/path/tests/MY_SCRIPT_tests.py", line 13, in test_MY_SCRIPT_MY_FUNCTION
    MY_SCRIPT = StatsGtMatrix()
  File "/my/home/path/scripts/MY_SCRIPT.py", line 84, in __init__
    super(StatsGtMatrix, self).__init__()
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/site-packages/basescript/basescript.py", line 29, in __init__
    self.args = self.parser.parse_args(args=args)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1755, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 1794, in parse_known_args
    self.error(str(err))
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 2508, in error
    self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
  File "/miniconda/path/envs/bioinfo_sdk/lib/python3.7/argparse.py", line 2495, in exit
    _sys.exit(status)
SystemExit: 2

----------------------------------------------------------------------
Ran 1 test in 0.005s

FAILED (errors=1)

Here is a sample from my unittest file :

import unittest
from unittest.mock import MagicMock

from scripts.my_script import MyScript, ClassA, ClassB

class MyScriptTests(unittest.TestCase):

    _fake_A_classes = [ClassA('ped1'), ClassA('ped2')]

    _fake_B_class = ClassB('ped1','A','A', False, False)

    def test_my_script_my_function(self):
        my_script = MyScript()
        my_script.A_classes = \
        MagicMock(
            return_value=self._fake_A_classes
        )

        returned_ped = my_script.my_function(self._fake_B_class)

        self.assertEqual('ped1', returned_ped.name)

and from my script :

...
class MyScript(BaseScript):
    # The following specifies the script description so that it be used
    # as a part of the usage doc when --help option is used during running.
    DESC = """
    Usage
    """

    def __init__(self):
        #this set class attribute
        super(MyScript, self).__init__()
        self.custom_array = []

    def define_args(self, parser):
        parser.add_argument('arg_one', type=str, help='input file path')

    def my_function(self, class_a: ClassA):
    # function I'm trying to test
        return class_a
...

It's not my real Classes, path, functions name.

I'm wondering how to run unittest for a basescript script ?

Any help would be appreciated.

Best regards

@jaswanth098
Copy link
Contributor

@foxpowa In your in your test cases you need to pass the subcommand that you need to run by default it would be run, Please check the below snippet

import unittest
from unittest.mock import MagicMock

from scripts.my_script import MyScript, ClassA, ClassB

class MyScriptTests(unittest.TestCase):

    _fake_A_classes = [ClassA('ped1'), ClassA('ped2')]

    _fake_B_class = ClassB('ped1','A','A', False, False)

    def test_my_script_my_function(self):
        my_script = MyScript(["run"]).start() # changed here
        my_script.A_classes = \
        MagicMock(
            return_value=self._fake_A_classes
        )

        returned_ped = my_script.my_function(self._fake_B_class)

        self.assertEqual('ped1', returned_ped.name)

if there is a necessary for passing any other command line arguments you need to take the string and split it using shlex

import shlex

arguments = shlex.split("run --arg_one /root/file")
# Now the arguments variabel should be given to your class intialization
# MyScript(arguments).start()

@tomraulet
Copy link
Author

Hi @jaswanth098,
thank you for your reply !

I've tested your snippet like this :

import unittest
from unittest.mock import MagicMock
import shlex

from scripts.my_script import MyScript, ClassA, ClassB

class MyScriptTests(unittest.TestCase):

    _fake_A_classes = [ClassA('ped1'), ClassA('ped2')]

    _fake_B_class = ClassB('ped1','A','A', False, False)

   def get_script_arg(self, args_string: str): # <---------------------------------
        return shlex.split(args_string)

    def test_my_script_my_function(self):
        args = self.get_script_arg("run my_file.txt") # <---------------------------------
        my_script = MyScript(args).start() # <---------------------------------
        my_script.A_classes = \
        MagicMock(
            return_value=self._fake_A_classes
        )

        returned_ped = my_script.my_function(self._fake_B_class)

        self.assertEqual('ped1', returned_ped.name)

and experienced this issue :

python -m unittest discover -s tests -p "*_tests.py"
...
Traceback (most recent call last):
  File "/path/to/repo/tests/my_script_tests.py", line 18, in test_my_script_my_function
    my_script = MyScript(args).start()
TypeError: __init__() takes 1 positional argument but 2 were given

Which seems legit to me, as __init__ function from MyScript take only self as arg.
Or am I missing something else ?

Best regards,

@jaswanth098
Copy link
Contributor

jaswanth098 commented Jan 28, 2020

@foxpowa, In that case, you can try something like below

class MyScript:
    def __init__(self, *args, **kwargs):
        # custom code
        super().__init__(*args, **kwargs)

Even custom arguments can be passed to your class
Eg:

class MyScript:
    def __init__(self, custom_args, *args, **kwargs):
        # custom code
        # you can do anything with custom_args but donot pass them to super
        super().__init__(*args, **kwargs)

BaseScript init function has to
NOTE: By the way above is python3 code

@jaswanth098
Copy link
Contributor

@foxpowa And one more thing in the above code after your run function execution is completed if you want to run my_function you need to change as below

import unittest
from unittest.mock import MagicMock
import shlex

from scripts.my_script import MyScript, ClassA, ClassB

class MyScriptTests(unittest.TestCase):

    _fake_A_classes = [ClassA('ped1'), ClassA('ped2')]

    _fake_B_class = ClassB('ped1','A','A', False, False)

   def get_script_arg(self, args_string: str): 
        return shlex.split(args_string)

    def test_my_script_my_function(self):
        args = self.get_script_arg("run my_file.txt")
        my_script = MyScript(args) # <---------------------------------
        my_script.start() # <---------------------------------
        my_script.A_classes = \
        MagicMock(
            return_value=self._fake_A_classes
        )

        returned_ped = my_script.my_function(self._fake_B_class)

        self.assertEqual('ped1', returned_ped.name)

@tomraulet
Copy link
Author

Thank you @jaswanth098

Your advice about

class MyScript:
    def __init__(self, *args, **kwargs):
        # custom code
        super().__init__(*args, **kwargs)

worked ;)

For unit test purposes, I don't even need to exec .start() to be able to unittest other function.

Thank you again !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants