Skip to content

test: Add new fake_fs fixture backed by pyfakefs#6785

Open
TheRealFalcon wants to merge 2 commits intocanonical:mainfrom
TheRealFalcon:pyfakefs
Open

test: Add new fake_fs fixture backed by pyfakefs#6785
TheRealFalcon wants to merge 2 commits intocanonical:mainfrom
TheRealFalcon:pyfakefs

Conversation

@TheRealFalcon
Copy link
Copy Markdown
Contributor

@TheRealFalcon TheRealFalcon commented Mar 9, 2026

Proposed Commit Message

test: Add new `fake_fs` fixture backed by pyfakefs

Also convert a few fake_filesystem tests to prove its usage:
- tests/unittests/config/test_cc_keyboard.py
- tests/unittests/config/test_cc_mounts.py
- tests/unittests/config/test_cc_update_etc_hosts.py
- tests/unittests/config/test_cc_puppet.py

Additional Context

I originally raised this idea in #6548 , though after working with it more closely, I don't think it's possible/easy to insert the new fixture as a simple shim. The way it would interact with tmpdir is incompatible with how fake_filesystem currently does, and tmpdir is core to fake_filesystem.

Because of this, I would like to propose it as a new fixture while deprecating the original fake_filesystem. Deprecation sounds big and scary and like a bigger maintenance burden, but I don't think that it has to be. Just because something is deprecated doesn't mean it needs to be removed or changed. It just means we shouldn't be writing new stuff ith it. Just like tmpdir and tmp_path co-exist peacefully in pytest, I think that fake_filesystem and fake_fs could co-exist peacefully here, with the assumption that new tests should use fake_fs instead of fake_filesystem, and that fake_filesystem won't be actively modified for any new use cases.

As mentioned in the discussion, the main reason I think we should prefer pyfakefs is because it is comprehensive. Even within the past year, new functions have been added to be patched by fake_filesystem. It's not a "complete" implementation, as it gets added to as new functions are used that need to be patched. That has worked ok, but it makes testing a way larger headache when you need to also update this fairly convoluted fixture. The biggest hole here is pathlib. In the past I have wanted to refactor some of our utility functions to support pathlib, but I eventually abandoned those efforts because I didn't want to deal with the fake_filesystem headache.

Furthermore, I think tests actually look a lot cleaner with pyfakefs. A common testing paradigm in this codebase is to patch some kind of "open file" call to instead redirect the path to a tmpdir based path that we've manually setup, and then test with that mocked version. With pyfakefs, that extra level of patching is no longer required. See the test_cc_puppet.py changes. Instead of local patching or fakes, the code under test can just use the expected absolute path and it all "just works".

I realize my implementation here changed what was agreed to in the discussion, so if this change doesn't fit the project plans, that's fine too.

Test Steps

Merge type

  • Squash merge using "Proposed Commit Message"
  • Rebase and merge unique commits. Requires commit messages per-commit each referencing the pull request number (#<PR_NUM>)

Also convert a few fake_filesystem tests to prove its usage:
- tests/unittests/config/test_cc_keyboard.py
- tests/unittests/config/test_cc_mounts.py
- tests/unittests/config/test_cc_update_etc_hosts.py
- tests/unittests/config/test_cc_puppet.py
@blackboxsw blackboxsw self-assigned this Mar 11, 2026
@github-actions github-actions bot added the stale-pr Pull request is stale; will be auto-closed soon label Mar 26, 2026
@canonical canonical deleted a comment from github-actions bot Mar 27, 2026
@github-actions github-actions bot removed the stale-pr Pull request is stale; will be auto-closed soon label Mar 28, 2026
Copy link
Copy Markdown
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

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

Thanks @TheRealFalcon. I think this approach looks good. I think it's worth also trying to create an issue to track the migration work to move away from fake_filesystem and retire that fixture from all unittests in favor of fake_fs. I believe it is prodent to not roll out our fake_filesystem when we can leverage a maintained solution from the broader community.


self.fstab_path = os.path.join(self.new_root, "etc/fstab")
def setup(self, mocker, fake_fs):
self._makedirs("/etc")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Would this not be converted to fake_fs.create_dir("/etc")?

@@ -75,8 +75,8 @@ def test_enable_fallback_on_failure(self, m_subp):
@pytest.mark.usefixtures("fake_filesystem")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this be fake_fs now?

Copy link
Copy Markdown
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

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

Minor change request as commented inline.

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.

2 participants