-
Notifications
You must be signed in to change notification settings - Fork 837
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
Add more integration tests #615
Add more integration tests #615
Conversation
b10805f
to
46fc4ac
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this change Lucas! You've clearly done a great job of understanding both the old and new test frameworks. My comments inline are generally either requests for docstring cleanup/clarification, or suggest that we parameterise some tests which I think would lend themselves to it well; this latter suggestion will involve understanding how class_client
works (vs client
), and you can see an example of this in test_users_groups.py
.
"""Integration test for the runcmd module. | ||
This test specifies a command to be executed by the ``runcmd`` module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per PEP-257, which we generally try to follow:
Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.
"""Integration test for the runcmd module. | |
This test specifies a command to be executed by the ``runcmd`` module | |
"""Integration test for the runcmd module. | |
This test specifies a command to be executed by the ``runcmd`` module |
(This is a nit, but an easily fixable one.)
@@ -0,0 +1,43 @@ | |||
"""Integration test for the set_hostname module. | |||
This test specifies a hostname and fqdn through the ``set_hostname`` module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test
This file is two tests, we should describe each of them separately. (This is particularly important because they are two test methods in a single class: people may very easily assume that you're using a class_client
based on this description, which makes it harder for them to understand what is going on.)
@@ -0,0 +1,27 @@ | |||
"""Integration test for the snap module. | |||
This test specifies a command to be executed by the ``runcmd`` module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runcmd
This needs an update.
assert "core" in snap_output | ||
assert "hello-world" in snap_output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps worth adding spaces here to reduce the likelihood that we match substrings elsewhere in the output?
assert "core" in snap_output | |
assert "hello-world" in snap_output | |
assert "core " in snap_output | |
assert "hello-world " in snap_output |
|
||
|
||
USER_DATA = """\ | ||
#cloud-config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all indented by two more spaces than necessary.
class TestSshKeysProvided: | ||
|
||
@pytest.mark.user_data(USER_DATA) | ||
def test_ssh_keys_provided(self, client): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like another good candidate for parameterisation, what do you think?
# NOTE: on trusty 'file' has an output formatting error for binary files and | ||
# has 2 spaces in 'LSB executable', which causes a failure here | ||
# |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't expect to run these tests against trusty, so I think we can drop this disclaimer:
# NOTE: on trusty 'file' has an output formatting error for binary files and | |
# has 2 spaces in 'LSB executable', which causes a failure here | |
# |
class TestWriteFiles: | ||
|
||
@pytest.mark.user_data(USER_DATA) | ||
def test_write_files(self, client): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another good candidate for parameterisation?
#cloud-config | ||
write_files: | ||
- encoding: b64 | ||
content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we are defining this string in Python, what do you think to doing something like:
ASCII_TEXT = "ASCII text"
B64_CONTENT = base64.b64encode(ASCII_TEXT)
and then using .format()
to include it in USER_DATA
?
This saves us from having the "ASCII text"
string defined only in the assertion code, which I think makes it easier to parse what is going on.
46fc4ac
to
7214b39
Compare
Thanks for the review @OddBloke. I think I have addressed all of the comments |
7214b39
to
1b4d1e9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Lucas, this is really good work! I have a couple of minor doc nits, which I'll apply myself before landing.
(I also have started a convo with James inline, perhaps we should take that to a different forum.)
tests/integration_tests/modules/test_ssh_auth_key_fingerprints.py
Outdated
Show resolved
Hide resolved
@pytest.mark.user_data(USER_DATA) | ||
class TestPackageUpdateUpgradeInstall: | ||
|
||
def assert_package_installed(self, pkg_out, name, version=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TheRealFalcon This assertion helper mirrors one in the cloud_tests/
which is used in multiple places: do you have any thoughts as to whether we should store such shared "test" code on client
, or elsewhere?
(No change needed as part of this PR, to be clear!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's a good question. I'm worried about seeing every conceivable helper function going into that class with implementations being nothing more than a series of execs or push/pulls and parsing what's returned, though I realize we're kind of already doing that with the install_*
and read/write methods.
Would it make sense to start putting these kinds of helper functions into separate files (not named util.py) and have the helper function take an IntegrationClient
as an argument?
tests/integration_tests/modules/test_package_update_upgrade_install.py
Outdated
Show resolved
Hide resolved
On Mon, Oct 19, 2020 at 01:41:47PM -0700, James Falcon wrote:
Yeah, that's a good question. I'm worried about seeing every
conceivable helper function going into that class with implementations
being nothing more than a series of execs or push/pulls and parsing
what's returned, though I realize we're kind of already doing that
with the `install_*` and read/write methods.
Yeah, agreed, I think it will make that namespace extremely noisy.
Would it make sense to start putting these kinds of helper functions
into separate files (not named util.py) and have the helper function
take an `IntegrationClient` as an argument?
In cloud-test-framework we had a class called `InstanceInteractions`,
which defined a bunch of these sorts of things (a quick sample:
`get_file`, `put_file`, `apt_get_update`) and in the instance class's
`__init__` we had: `self.interactions = InstanceInteractions(self)`.
That gives you a separate namespace (`instance.interactions.`) which is
accessible directly on the objects to which it applies, and which
handles passing in the correct first argument for you.
I think this would work pretty well here too, what do you think?
(One note: asserting was handled completely differently in c-t-f, so we
may find that having several namespaces might suit our purposes better:
.interactions and .assertions, for example).
|
Yeah, that's a good option too. It makes the calling semantics a nicer. I do get a little nervous about having the IntegrationClient "own" these additional modules when it doesn't really need to. Tradeoffs either way I guess. |
Translate tests from
cloud_test
to the new integration test framework.We are translating the following tests: