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

Improve type validation tests #134

Merged
merged 12 commits into from Apr 3, 2020
133 changes: 133 additions & 0 deletions tests/lib_testslide.py
@@ -0,0 +1,133 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from testslide.dsl import context, xcontext, fcontext, Skip # noqa: F401
import testslide.lib
from . import sample_module
from testslide import StrictMock
import unittest.mock


@context("_validate_function_signature")
def _validate_function_signature(context):
@context.sub_context
def valid_types(context):
@context.function
def assert_passes(self, *args, **kwargs):
testslide.lib._validate_function_signature(
sample_module.test_function, args, kwargs
)

@context.example
def canonical(self):
self.assert_passes("arg1", "arg2", kwarg1="kwarg1", kwarg2="kwarg2")

@context.example
def kwargs_as_args(self):
self.assert_passes("arg1", "arg2", "kwarg1", "kwarg2")
self.assert_passes("arg1", "arg2", "kwarg1", kwarg2="kwarg2")

@context.example
def args_as_kwargs(self):
self.assert_passes("arg1", arg2="arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes(
arg1="arg1", arg2="arg2", kwarg1="kwarg1", kwarg2="kwarg2"
)

@context.example("testslide.StrictMock with valid template")
def testslide_StrictMock_with_valid_template(self):
strict_mock = StrictMock(template=str)
self.assert_passes(strict_mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", strict_mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1=strict_mock, kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1="kwarg1", kwarg2=strict_mock)

@context.example("testslide.StrictMock without template")
def testslide_StrictMock_without_template(self):
strict_mock = StrictMock()
self.assert_passes(strict_mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", strict_mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1=strict_mock, kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1="kwarg1", kwarg2=strict_mock)

@context.example("unittest.mock.Mock with valid spec")
def unittest_mock_Mock_with_valid_spec(self):
mock = unittest.mock.Mock(spec=str)
self.assert_passes(mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1=mock, kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1="kwarg1", kwarg2=mock)

@context.example("unittest.mock.Mock without spec")
def unittest_mock_Mock_without_spec(self):
mock = unittest.mock.Mock()
self.assert_passes(mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1=mock, kwarg2="kwarg2")
self.assert_passes("arg1", "arg2", kwarg1="kwarg1", kwarg2=mock)

@context.sub_context
def invalid_types(context):
@context.function
def assert_fails(self, *args, **kwargs):
with self.assertRaisesRegex(
TypeError, "Call with incompatible argument types"
):
testslide.lib._validate_function_signature(
sample_module.test_function, args, kwargs
)

@context.example
def error_message(self):
with self.assertRaises(
TypeError,
msg=(
"Call with incompatible argument types:\n"
" 'arg1': type of arg1 must be str; got int instead\n"
" 'arg2': type of arg2 must be str; got int instead\n"
" 'kwarg1': type of kwarg1 must be str; got int instead\n"
" 'kwarg2': type of kwarg2 must be str; got int instead"
),
):
testslide.lib._validate_function_signature(
sample_module.test_function, (1, 2, 3, 4), {}
)

@context.example
def canonical(self):
self.assert_fails(1, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", 2, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1=1, kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1="kwarg1", kwarg2=2)

@context.example
def kwargs_as_args(self):
self.assert_fails("arg1", "arg2", 1, "kwarg2")
self.assert_fails("arg1", "arg2", "kwarg1", 2)
self.assert_fails("arg1", "arg2", 1, kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", "kwargs1", kwarg2=2)

@context.example
def args_as_kwargs(self):
self.assert_fails(arg1=1, arg2="arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails(arg1="arg1", arg2=2, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails(arg1="arg1", arg2="arg2", kwarg1=1, kwarg2="kwarg2")
self.assert_fails(arg1="arg1", arg2="arg2", kwarg1="kwarg1", kwarg2=2)

@context.example("testslide.StrictMock with invalid template")
def testslide_StrictMock_with_invalid_template(self):
strict_mock = StrictMock(template=int)
self.assert_fails(strict_mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", strict_mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1=strict_mock, kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1="kwarg1", kwarg2=strict_mock)

@context.example("unittest.mock.Mock with valid spec")
def unittest_mock_Mock_with_valid_spec(self):
mock = unittest.mock.Mock(spec=int)
self.assert_fails(mock, "arg2", kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", mock, kwarg1="kwarg1", kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1=mock, kwarg2="kwarg2")
self.assert_fails("arg1", "arg2", kwarg1="kwarg1", kwarg2=mock)
9 changes: 4 additions & 5 deletions tests/matchers_unittest.py
Expand Up @@ -282,10 +282,9 @@ def testCannotChainMoreThanTwo(self):
class TestUsageWithPatchCallable(testslide.TestCase):
def test_patch_callable(self):
self.mock_callable(sample_module, "test_function").for_call(
testslide.matchers.AnyInstanceOf(str)
& testslide.matchers.RegexMatches("test.*"),
testslide.matchers.IntBetween(2, 4),
testslide.matchers.RegexMatches("foo"),
testslide.matchers.RegexMatches("bar"),
).to_return_value("mocked_response")
with self.assertRaises(testslide.mock_callable.UnexpectedCallArguments):
sample_module.test_function(2, 5)
sample_module.test_function("testing", 3)
sample_module.test_function("meh", "moh")
sample_module.test_function("foo", "bar")