Skip to content

Commit

Permalink
Refactor fluent API unit tests.
Browse files Browse the repository at this point in the history
The so-called fluent API unit tests are intermingled with the notecard.py tests
in test_notecard.py. This commit separates these tests out into their own
individual test files, corresponding to their respective modules (e.g. the
methods in card.py are tested by test_card.py). This commit also adds a
conftest.py that defines fixtures for testing the fluent APIs, since they all
follow a very similar pattern. Specifically, these fixtures test that

- The fluent API calls the Notecard API correctly.
- The fluent API requires a valid Notecard object.
  • Loading branch information
haydenroche5 committed Sep 14, 2023
1 parent 5d55bfd commit faa8d0c
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 280 deletions.
43 changes: 43 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import sys
import os
import pytest
from unittest.mock import MagicMock

sys.path.insert(0,
os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import notecard # noqa: E402


@pytest.fixture
def run_fluent_api_notecard_api_mapping_test():
def _run_test(fluent_api, notecard_api_name, req_params, rename_map=None):
card = notecard.Notecard()
card.Transaction = MagicMock()

fluent_api(card, **req_params)
expected_notecard_api_req = {'req': notecard_api_name, **req_params}

# There are certain fluent APIs that have keyword arguments that don't
# map exactly onto the Notecard API. For example, note.changes takes a
# 'maximum' parameter, but in the JSON request that gets sent to the
# Notecard, it's sent as 'max'. The rename_map allows a test to specify
# how a fluent API's keyword args map to Notecard API args, in cases
# where they differ.
if rename_map is not None:
for old_key, new_key in rename_map.items():
expected_notecard_api_req[new_key] = expected_notecard_api_req.pop(old_key)

card.Transaction.assert_called_once_with(expected_notecard_api_req)

return _run_test


@pytest.fixture
def run_fluent_api_invalid_notecard_test():
def _run_test(fluent_api, req_params):
with pytest.raises(Exception, match='Notecard object required'):
# Call with None instead of a valid Notecard object.
fluent_api(None, **req_params)

return _run_test
69 changes: 69 additions & 0 deletions test/test_card.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import pytest
from notecard import card


@pytest.mark.parametrize(
'fluent_api,notecard_api,req_params',
[
(
card.attn,
'card.attn',
{
'mode': 'arm',
'files': ['data.qi', 'my-settings.db'],
'seconds': 60,
'payload': 'ewogICJpbnRlcnZhbHMiOiI2MCwxMiwxNCIKfQ==',
'start': True
}
),
(
card.status,
'card.status',
{}
),
(
card.time,
'card.time',
{}
),
(
card.temp,
'card.temp',
{'minutes': 5}
),
(
card.version,
'card.version',
{}
),
(
card.voltage,
'card.voltage',
{
'hours': 1,
'offset': 2,
'vmax': 1.1,
'vmin': 1.2
}
),
(
card.wireless,
'card.wireless',
{
'mode': 'auto',
'apn': 'myapn.nb'
}
)
]
)
class TestCard:
def test_fluent_api_maps_notecard_api_correctly(
self, fluent_api, notecard_api, req_params,
run_fluent_api_notecard_api_mapping_test):
run_fluent_api_notecard_api_mapping_test(fluent_api, notecard_api,
req_params)

def test_fluent_api_fails_with_invalid_notecard(
self, fluent_api, notecard_api, req_params,
run_fluent_api_invalid_notecard_test):
run_fluent_api_invalid_notecard_test(fluent_api, req_params)
40 changes: 40 additions & 0 deletions test/test_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pytest
from notecard import env


@pytest.mark.parametrize(
'fluent_api,notecard_api,req_params',
[
(
env.default,
'env.default',
{'name': 'my_var', 'text': 'my_text'}
),
(
env.get,
'env.get',
{'name': 'my_var'}
),
(
env.modified,
'env.modified',
{}
),
(
env.set,
'env.set',
{'name': 'my_var', 'text': 'my_text'}
)
]
)
class TestEnv:
def test_fluent_api_maps_notecard_api_correctly(
self, fluent_api, notecard_api, req_params,
run_fluent_api_notecard_api_mapping_test):
run_fluent_api_notecard_api_mapping_test(fluent_api, notecard_api,
req_params)

def test_fluent_api_fails_with_invalid_notecard(
self, fluent_api, notecard_api, req_params,
run_fluent_api_invalid_notecard_test):
run_fluent_api_invalid_notecard_test(fluent_api, req_params)
45 changes: 45 additions & 0 deletions test/test_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest
from notecard import file


@pytest.mark.parametrize(
'fluent_api,notecard_api,req_params',
[
(
file.changes,
'file.changes',
{
'tracker': 'tracker',
'files': ['file_1', 'file_2', 'file_3']
}
),
(
file.delete,
'file.delete',
{
'files': ['file_1', 'file_2', 'file_3']
}
),
(
file.stats,
'file.stats',
{}
),
(
file.pendingChanges,
'file.changes.pending',
{}
)
]
)
class TestFile:
def test_fluent_api_maps_notecard_api_correctly(
self, fluent_api, notecard_api, req_params,
run_fluent_api_notecard_api_mapping_test):
run_fluent_api_notecard_api_mapping_test(fluent_api, notecard_api,
req_params)

def test_fluent_api_fails_with_invalid_notecard(
self, fluent_api, notecard_api, req_params,
run_fluent_api_invalid_notecard_test):
run_fluent_api_invalid_notecard_test(fluent_api, req_params)
66 changes: 66 additions & 0 deletions test/test_hub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import pytest
from notecard import hub


@pytest.mark.parametrize(
'fluent_api,notecard_api,req_params',
[
(
hub.get,
'hub.get',
{}
),
(
hub.log,
'hub.log',
{
'text': 'com.blues.tester',
'alert': True,
'sync': True
}
),
(
hub.set,
'hub.set',
{
'product': 'com.blues.tester',
'sn': 'foo',
'mode': 'continuous',
'outbound': 2,
'inbound': 60,
'duration': 5,
'sync': True,
'align': True,
'voutbound': '2.3',
'vinbound': '3.3',
'host': 'http://hub.blues.foo'
}
),
(
hub.status,
'hub.status',
{}
),
(
hub.sync,
'hub.sync',
{}
),
(
hub.syncStatus,
'hub.sync.status',
{'sync': True}
)
]
)
class TestHub:
def test_fluent_api_maps_notecard_api_correctly(
self, fluent_api, notecard_api, req_params,
run_fluent_api_notecard_api_mapping_test):
run_fluent_api_notecard_api_mapping_test(fluent_api, notecard_api,
req_params)

def test_fluent_api_fails_with_invalid_notecard(
self, fluent_api, notecard_api, req_params,
run_fluent_api_invalid_notecard_test):
run_fluent_api_invalid_notecard_test(fluent_api, req_params)
94 changes: 94 additions & 0 deletions test/test_note.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pytest
from notecard import note


@pytest.mark.parametrize(
'fluent_api,notecard_api,req_params,rename_map',
[
(
note.add,
'note.add',
{
'file': 'data.qo',
'body': {'key_a:', 'val_a', 'key_b', 42},
'payload': 'ewogICJpbnRlcnZhbHMiOiI2MCwxMiwxNCIKfQ==',
'sync': True
},
None
),
(
note.changes,
'note.changes',
{
'file': 'my-settings.db',
'tracker': 'inbound-tracker',
'maximum': 2,
'start': True,
'stop': True,
'delete': True,
'deleted': True
},
{
'maximum': 'max'
}
),
(
note.delete,
'note.delete',
{
'file': 'my-settings.db',
'note_id': 'my_note',
},
{
'note_id': 'note'
}
),
(
note.get,
'note.get',
{
'file': 'my-settings.db',
'note_id': 'my_note',
'delete': True,
'deleted': True
},
{
'note_id': 'note'
}
),
(
note.template,
'note.template',
{
'file': 'my-settings.db',
'body': {'key_a:', 'val_a', 'key_b', 42},
'length': 42
},
None
),
(
note.update,
'note.update',
{
'file': 'my-settings.db',
'note_id': 'my_note',
'body': {'key_a:', 'val_a', 'key_b', 42},
'payload': 'ewogICJpbnRlcnZhbHMiOiI2MCwxMiwxNCIKfQ=='
},
{
'note_id': 'note'
}
)
]
)
class TestNote:
def test_fluent_api_maps_notecard_api_correctly(
self, fluent_api, notecard_api, req_params, rename_map,
run_fluent_api_notecard_api_mapping_test):
run_fluent_api_notecard_api_mapping_test(fluent_api, notecard_api,
req_params, rename_map)

def test_fluent_api_fails_with_invalid_notecard(
self, fluent_api, notecard_api, req_params, rename_map,
run_fluent_api_invalid_notecard_test):
run_fluent_api_invalid_notecard_test(fluent_api, req_params)
Loading

0 comments on commit faa8d0c

Please sign in to comment.