beets/test/plugins
Šarūnas Nejus 3b670cdf18
In test I/O utility, restore the old stdin/stdout instead of the "true" I/O streams (#5049)
I got a little bit nerdsniped by the problems observed in #5027. In
short, my high-level diagnosis in
https://github.com/beetbox/beets/pull/5027#issuecomment-1857953929 seems
to have been correct: other tests were suppressing the legitimate
failure of a flaky test.

I found the problem by running other tests before the problem test, like
this:

```
$ pytest -k 'test_nonexistant_db or test_delete_removes_item' test/test_ui.py
```

When running `test_nonexistant_db` alone, it fails. When running it like
this with another test that goes first, it passes. That's the problem.

However, `test_delete_removes_item` is just one example that works to
make this problem happen. It appeared that _any_ test in a class that
used our `_common.TestCase` base class had this power. I tracked down
the issue to our `DummyIO` utility, which was having an unintentional
effect even when it was never actually used.

Here's the solution. Instead of restoring `sys.stdin` to
`sys.__stdin__`, we now restore it to whatever it was before we
installed out dummy I/O hooks. This is relevant in pytest, for example,
which installs its *own* `sys.stdin`, which we were then clobbering.
This was leading to the suppression of test failures observed in #5021
and addressed in #5027.

The CI will fail for this PR because it now (correctly) exposes a
failing test. Hopefully by combining this with the fixes in the works in
#5027, we'll be back to a passing test suite. 😃 @Phil305, could
you perhaps help validate that hypothesis?

Edit: @snejus:

I've now consolidated test I/O handling by removing the legacy
`control_stdin`/`capture_stdout` context managers and the custom
`DummyOut` stream, replacing them with a pytest-driven `io` fixture
that:
- provides controllable `stdin` via a lightweight `DummyIn`
- captures `stdout` via `capteesys`
- attaches a `DummyIO` helper to test classes as `self.io`
2026-02-14 18:03:34 +00:00
..
utils Format MusicBrainz search terms and escape Lucene special chars 2026-02-07 22:26:17 +00:00
__init__.py Correctly refactor tests 2023-10-17 19:39:03 +10:00
conftest.py Migrate mbcollection to use MusicBrainzAPI 2026-01-06 09:54:02 +00:00
lyrics_pages.py Address RUF012 2026-01-13 20:55:40 +00:00
test_acousticbrainz.py Reformat the codebase 2024-09-21 11:57:48 +01:00
test_advancedrewrite.py Update CI config, minimum ruff version, docs and add changelog note 2024-12-10 06:10:03 +00:00
test_albumtypes.py Configure future-annotations 2026-01-13 20:55:40 +00:00
test_art.py fetchart: Add support for configurable fallback cover art 2025-12-30 13:45:03 +01:00
test_aura.py Configure future-annotations 2026-01-13 20:55:40 +00:00
test_autobpm.py Skip autobpm tests if librosa isn't available 2024-11-30 09:32:08 -04:00
test_bareasc.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_beatport.py Use unittest.TestCase for tests that don't require the dir setup 2025-05-26 12:40:38 +01:00
test_bpd.py Replace control_stdin with io.addinput 2026-02-10 00:53:20 +00:00
test_bucket.py Future proof BucketPluginTest.test_year_single_year_last_folder 2024-12-27 16:28:38 -04:00
test_convert.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_discogs.py Remove utils, rework from_plugin method in ArtistState to from_config 2026-01-19 12:43:30 -08:00
test_edit.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_embedart.py Fix lint 2025-11-20 18:48:37 +01:00
test_embyupdate.py Fix formatting 2025-05-07 10:41:01 +01:00
test_export.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_fetchart.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_filefilter.py Reformat the codebase 2024-09-21 11:57:48 +01:00
test_fromfilename.py Refactor tests using pytest 2025-09-30 15:54:33 +02:00
test_ftintitle.py Fix test failures 2026-02-10 00:53:20 +00:00
test_hook.py Address RUF012 2026-01-13 20:55:40 +00:00
test_ihate.py Replace assertFalse 2024-08-12 08:43:41 +01:00
test_importadded.py Replace string concatenation (' + ') 2025-08-30 23:10:15 +01:00
test_importfeeds.py pyupgrade Python 3.10 2025-11-08 12:09:52 +00:00
test_importsource.py Replace control_stdin with io.addinput 2026-02-10 00:53:20 +00:00
test_info.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_inline.py Fixed unit tests import 2025-11-25 18:41:31 -05:00
test_ipfs.py Replace format calls with f-strings 2025-08-30 18:42:26 +01:00
test_keyfinder.py Replace assertEqual 2024-08-12 08:43:42 +01:00
test_lastgenre.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_limit.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_listenbrainz.py Migrate listenbrainz plugin to use our MusicBrainzAPI implementation 2026-01-06 00:27:36 +00:00
test_lyrics.py Enable RUF rules 2026-01-13 20:55:40 +00:00
test_mbcollection.py mbcollection: slight refactor 2026-01-06 09:54:02 +00:00
test_mbpseudo.py Configure future-annotations 2026-01-13 20:55:40 +00:00
test_mbsubmit.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_mbsync.py Fixed imports for all tests and added a bit of stricter type checking. 2025-07-15 15:03:14 +02:00
test_missing.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_mpdstats.py Address RUF012 2026-01-13 20:55:40 +00:00
test_musicbrainz.py test added 2026-02-11 18:23:55 +01:00
test_parentwork.py Migrate parentwork to use MusicBrainzAPI 2026-01-06 00:27:36 +00:00
test_permissions.py Replace assertPrem 2025-07-09 09:21:52 +01:00
test_play.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_playlist.py Replace string concatenation (' + ') 2025-08-30 23:10:15 +01:00
test_plexupdate.py Replace string concatenation (' + ') 2025-08-30 23:10:15 +01:00
test_plugin_mediafield.py Replace string concatenation (' + ') 2025-08-30 23:10:15 +01:00
test_random.py Readded licence. Removed last legacy occurrences of artist and 2026-01-30 00:30:21 +00:00
test_replace.py Feat: Add replace plugin (#5644) 2025-05-27 00:17:52 +02:00
test_replaygain.py Replace format calls with f-strings 2025-08-30 18:42:26 +01:00
test_scrub.py Move scrub test to a separate file 2025-05-17 03:32:00 +01:00
test_smartplaylist.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_spotify.py expand tests to include check for track artists 2025-12-18 16:23:58 -08:00
test_subsonicupdate.py Use unittest.TestCase for tests that don't require the dir setup 2025-05-26 12:40:38 +01:00
test_substitute.py Replace string concatenation (' + ') 2025-08-30 23:10:15 +01:00
test_the.py Use unittest.TestCase for tests that don't require the dir setup 2025-05-26 12:40:38 +01:00
test_thumbnails.py Remove no-op decargs 2025-07-08 11:37:33 +01:00
test_titlecase.py Cleanup, fix format 2025-12-16 19:06:37 -08:00
test_types_plugin.py Replace capture_output with io.getoutput 2026-02-10 00:53:20 +00:00
test_web.py plugins/web: fix endpoints /…/values/… 2025-11-15 21:02:38 +01:00
test_zero.py Replace control_stdin with io.addinput 2026-02-10 00:53:20 +00:00