Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@pytest.mark.parametrize
replacement working with unittest.TestCase
You want to start using @pytest.mark.parametrize
, but can't simply drop unittest.TestCase
because you have tons of self.assert
's, setUp
's tearDown
's to rewrite?
With @parametrize
you can start parameterizing your tests now, and get rid of unittest.TestCase
later if needed.
import unittest
from parametrize import parametrize
class TestSomething(unittest.TestCase):
@parametrize('test_input,expected', [("3+5", 8), ("2+4", 6)])
def test_eval(self, test_input, expected):
self.assertEqual(expected, eval(test_input))
$ python -m unittest test.py -v
test_eval[2+4-6] (test.TestSomething) ... ok
test_eval[3+5-8] (test.TestSomething) ... ok
test_eval[6*9-42] (test.TestSomething) ... FAIL
======================================================================
FAIL: test_eval[6*9-42] (test.TestSomething)
----------------------------------------------------------------------
Traceback (most recent call last):
File "parametrize/parametrize.py", line 261, in parametrized_method
return parametrized_func(*args, **kwargs)
File "test.py", line 8, in test_eval
self.assertEqual(expected, eval(test_input))
AssertionError: 42 != 54
----------------------------------------------------------------------
Ran 3 tests in 0.001s
FAILED (failures=1)
import unittest
from parametrize import parametrize
class TestSomething(unittest.TestCase):
@parametrize("x", [0, 1])
@parametrize("y", [2, 3])
def test_foo(self, x, y):
pass
test_foo
will be called with: (x=0, y=2)
, (x=1, y=2)
, (x=0, y=3)
, and (x=1, y=3)
:
$ python -m unittest test.py -v
test_foo[2-0] (test.TestSomething) ... ok
test_foo[2-1] (test.TestSomething) ... ok
test_foo[3-0] (test.TestSomething) ... ok
test_foo[3-1] (test.TestSomething) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
Any @parametrize
decorator can be converted to @pytest.mark.parametrize
just by changing its name.
@pytest.mark.parametrize
decorator can be converted to @parametrize
as long as pytest.param
, indirect
, ids
and scope
are not used.
@parametrize
works with both unittest
and pytest
. However, pytest
is recommended due to limitations when using unittest in cli.
Parametrized tests are properly detected and handled by PyCharm. They are displayed as if they were parametrized with @pytest.mark.parametrize
.
Since @parametrize
does some kind of magic under the hood, there are some limitations you need to consider.
It's likely you will never face most of them, but if you will, @parametrize
will let you know with an error:
:white_check_mark: OK
@parametrize('a', (1, 2))
def f(a):
...
:x: Won't work:
def f(a):
...
parametrize('a', (1, 2))(func)
RuntimeError: Unable to find any parametrizes in decorators, please rewrite decorator name to match any of detected names @{'parametrize'}
:white_check_mark: OK:
@parametrize("a", (1, 2))
@parametrize("b", (2, 3))
@mock.patch(f"{__name__}.bar", "foo")
def f(a, b):
return a, b
:x: Won't work:
@mock.patch(f"{__name__}.bar", "foo")
@parametrize("a", (1, 2))
@parametrize("b", (2, 3))
def f(a, b):
return a, b
TypeError: @mock.patch(f"{__name__}.bar", "foo") must be defined before any of @{'parametrize'} decorators
locals()
or globals()
namespaces::white_check_mark: OK:
a_parameters = parametrize("a", (4, 5)) # defined in module
def func():
class TestSomething:
b_parameters = parametrize("b", (1, 2, 3))
@b_parameters # b_parameters found in locals()
@a_parameters # a_parameters found in globals()
def test_method(self, a, b):
...
:x: Won't work:
def func():
# defined in function scope
a_parameters = parametrize("a", (4, 5))
class TestSomething:
print('a_parameters' in {**globals(), **locals()}) # False
@a_parameters # accessed in class body scope
def test_method(self, a, b):
...
RuntimeError: Unable to find any parametrizes in decorators, please rewrite decorator name to match any of detected names @{'parametrize'}
$ cat test.py
import unittest
from parametrize import parametrize
class TestSomething(unittest.TestCase):
@parametrize('a', (1, 2))
def test_something(self, a):
self.assertIsInstance(a, int)
:white_check_mark: OK:
$ pytest test.py::TestSomething::test_something -v
...
test.py::TestSomething.test_something[1] ✓ 50% █████
test.py::TestSomething.test_something[2] ✓ 100% ██████████
Results (0.07s):
2 passed
:x: Won't work:
$ python -m unittest test.TestSomething.test_something
Traceback (most recent call last):
...
TypeError: don't know how to make test from: test_something[...]
@parametrize
cannot be used in interactive environments like REPL (It works in IPython though)@parametrize
cannot be used in cythonized codeFAQs
Drop-in @pytest.mark.parametrize replacement working with unittest.TestCase
We found that parametrize demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.