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

feat(test): Add tests for MOTD #202

Merged
merged 2 commits into from
Jun 21, 2024

Conversation

m-horky
Copy link
Contributor

@m-horky m-horky commented Mar 19, 2024

  • Card ID: CCT-414
  • Card ID: CCT-415

integration-tests/test_motd.py Outdated Show resolved Hide resolved
integration-tests/test_motd.py Outdated Show resolved Hide resolved
integration-tests/test_motd.py Outdated Show resolved Hide resolved
integration-tests/test_motd.py Outdated Show resolved Hide resolved
integration-tests/test_motd.py Outdated Show resolved Hide resolved
@m-horky m-horky force-pushed the motd-integration-tests branch 3 times, most recently from 44d150e to 88f2845 Compare March 22, 2024 15:06
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
@m-horky
Copy link
Contributor Author

m-horky commented May 29, 2024

Rawhide test failure is addressed by #245

src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
@m-horky m-horky force-pushed the motd-integration-tests branch 2 times, most recently from a5013e3 to 9dc1573 Compare May 31, 2024 11:07
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
@m-horky m-horky force-pushed the motd-integration-tests branch 2 times, most recently from 0dbf17c to d5a2300 Compare June 10, 2024 15:22
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
Comment on lines 80 to 83

# It stays absent when run multiple times.
insights_client.update_motd_message()
assert not (mock_fs.chroot / "etc/motd.d/insights-client").exists()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# It stays absent when run multiple times.
insights_client.update_motd_message()
assert not (mock_fs.chroot / "etc/motd.d/insights-client").exists()

src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
Comment on lines 90 to 101
def test_ignored_on_dev_null(mock_fs):
# When the /etc/motd.d/insights-client is a symbolic link to /dev/null...
(mock_fs.chroot / "etc/motd.d/insights-client").symlink_to(pathlib.Path(os.devnull))

# ...it should not be overwritten...
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)

# ...whether the MOTD file should be present or not.
(mock_fs.chroot / "etc/insights-client/.registered").open("w").close()
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_ignored_on_dev_null(mock_fs):
# When the /etc/motd.d/insights-client is a symbolic link to /dev/null...
(mock_fs.chroot / "etc/motd.d/insights-client").symlink_to(pathlib.Path(os.devnull))
# ...it should not be overwritten...
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)
# ...whether the MOTD file should be present or not.
(mock_fs.chroot / "etc/insights-client/.registered").open("w").close()
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)
def test_ignored_on_dev_null(mock_fs):
# When the /etc/motd.d/insights-client is a symbolic link to /dev/null...
(mock_fs.chroot / "etc/motd.d/insights-client").symlink_to(pathlib.Path(os.devnull))
# ...it should not be overwritten...
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)
@pytest.mark.parametrize(
["dot_file"],
[
("etc/insights-client/.registered",),
("etc/insights-client/.unregistered",),
]
)
def test_ignored_on_dev_null_and_dot_file(mock_fs, dot_file):
# When the /etc/motd.d/insights-client is a symbolic link to /dev/null...
(mock_fs.chroot / "etc/motd.d/insights-client").symlink_to(pathlib.Path(os.devnull))
# ...it should not be overwritten whether the MOTD file should be present or not.
(mock_fs.chroot / dot_file).open("w").close()
insights_client.update_motd_message()
assert (mock_fs.chroot / "etc/motd.d/insights-client").samefile(os.devnull)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I still don't agree. These tests are state-based, not action-based. The unit test ensures the files is (not) present, and we verify it through one or two paths to get there. Let's not go philosophical.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The philosophy behind the code is as important as the code itself. Otherwise it’s not possible to be correct and consistent.

@property
def chroot(self) -> pathlib.Path:
return pathlib.Path(self._dir.name)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought up a way how to get the paths from the patches in a more cocsise may. I am not entirely sure about the semantics, but it doesn’t feel completely off either.

Suggested change
def __getitem__(self, key):
self.patches[key].new

A magic method like this would allow calls like mock_fs["insights_client.MOTD_FILE"]. Imagine:

assert not mock_fs["insights_client.MOTD_FILE"].exists()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's getting complicated. It is not a production code. I prefer readability over smartness in tests, it can save you significant amount of time when it goes wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert not mock_fs["insights_client.MOTD_FILE"].exists()

IMHO this is not logically correct: the idea of the tests is to check for the actual paths, not on the names of the mocks (which are the internal modules/variables in the code).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, though, the internal name only serves as a string key to grab the path defined here in the tests.

Copy link
Contributor

@Glutexo Glutexo Jun 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole MockFS class with its seven methods already brings a great amount of smartness, and thus reducing streamlineliness.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, though, the internal name only serves as a string key to grab the path defined here in the tests.

That's still missing the point of what I wrote above: the fact that there are mocks to redirect the file operation is a semi-internal implementation detail of the test. The point of the test is checking the resulting paths (that they exist, or what they are, etc), and thus it is correct to use their names in checks/assertions. Once the mocks are set up, from the POV of the tests they should "not be seen" (other than using mock_fs for checks).

So no to your proposal: using the names of the mocks in tests is logically wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole MockFS class with its seven methods already brings a great amount of smartness, and thus reducing streamlineliness.

What is "streamlineliness" supposed to mean exactly? And mostly important, what's the whole point of your sentence? Please: rather than using nicely sounding words/sentences, provide actual/actionable points.

@m-horky
Copy link
Contributor Author

m-horky commented Jun 20, 2024

I've introduced further changes that should make the tests more readable. The MockFS now wraps the calls we're using (touch, exists) in a small interface that abstracts away the chroot completely.

src/insights_client/tests/test_motd.py Outdated Show resolved Hide resolved
@property
def chroot(self) -> pathlib.Path:
return pathlib.Path(self._dir.name)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert not mock_fs["insights_client.MOTD_FILE"].exists()

IMHO this is not logically correct: the idea of the tests is to check for the actual paths, not on the names of the mocks (which are the internal modules/variables in the code).

@m-horky m-horky force-pushed the motd-integration-tests branch 3 times, most recently from e98be87 to d0e42b0 Compare June 21, 2024 10:46
@Archana-PandeyM
Copy link
Collaborator

motd tests failed downstream. Please analyse the failure.

@Archana-PandeyM
Copy link
Collaborator

LGTM. Downstream tests failed because those are running on older version of insights.

@Archana-PandeyM Archana-PandeyM merged commit 3350f2f into RedHatInsights:master Jun 21, 2024
20 of 21 checks passed
@m-horky m-horky deleted the motd-integration-tests branch June 21, 2024 13:49
def _chroot(self) -> pathlib.Path:
return pathlib.Path(self._dir.name)

def touch(self, path: str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the touch command is often (mis)used to create a file, it’s primary intended purpose is to set a timestamp. Since this method only mimics the side-effect and not the original function, the name is misleading.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from touch (5):

Update the access and modification times of each FILE to the current time.
A FILE argument that does not exist is created empty,

The first paragraph documents this behavior. It is not misleading, touch is really common when you want to create an empty file on UNIX-like systems.

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

Successfully merging this pull request may close these issues.

4 participants