1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-13 19:54:15 +08:00

Assorted test deflaking (#37191)

A few quick ones from https://github.com/ppy/osu/issues/37190.

## [Rewrite `TestSceneDeleteLocalScore` to have less context menu
containers (and hopefully no longer
flake)](https://github.com/ppy/osu/commit/ea0bc5b72374056d1749f8058f4874b7ef66a241)

As seen in
https://github.com/ppy/osu/actions/runs/23890777748#user-content-r3s3.

This is a speculative fix but I'm feeling somewhat confident about this
one.

`BeatmapLeaderboardWedge` has TWO separate `ContextMenuContainer`s
itself, and the test mentioned here was bringing a third. I have a
feeling that the test flaking may have something to do with the fact
that the test logic would attempt to click a menu item on specifically
ONE of the three context menus. My bet is that when it fails, it's
because it's trying the wrong one, but I don't have reproduction.

## [Wait for text to appear in flaking
`TestSceneDrawableRoomPlaylist.TestSelectableMouseHandling`
test](https://github.com/ppy/osu/commit/9d62eea8b56a0eb013e8116db0d38424b500876f)

As seen in
https://github.com/ppy/osu/actions/runs/23888446400#user-content-r1s1.

Speculative. Banking on the fact that it takes time to load the sprite
texts.

## [Remove all tests from `TestSceneWikiMarkdownContainer` dependent on
existence of wiki on
dev](https://github.com/ppy/osu/commit/8f319f91c98510b84e915bb61ec147618a584ce1)

Deletes a flaky as seen in
https://github.com/ppy/osu/actions/runs/23878899702#user-content-r2s2.

The year is 2026 and LLM scrapers hammer [the
entire](https://sourcehut.org/blog/2025-04-15-you-cannot-have-our-users-data/)
[internet](https://blog.metabrainz.org/2025/12/11/we-cant-have-nice-things-because-of-ai-scrapers/)
all over to scrape whatever ounce of Human Content there is left to feed
the Moloch so that it can regurgitate it back in the form of The Most
Average Speech You've Ever Read. We are not immune to this, and as such
the LLM homunculi have hit the dev.ppy.sh wiki instance enough times for
it to just completely [be banished to the
blagole](https://www.youtube.com/watch?v=AfA_2Ku1aJY).

Which means I get to freely delete flaky tests that should never have
been running as part of CI because they're completely useless now and
it's not like we're ever turning them back on again.

## [Use equality check in
`TestSceneBeatmapCarouselScrolling.TestScrollPositionMaintainedOnRemove_SecondSelected`
that's less sensitive to floating
point](https://github.com/ppy/osu/commit/6f2a1de58f7e816830c430e89117ee4c594f529d)

As seen in
https://github.com/ppy/osu/actions/runs/23826420794#user-content-r0s1.
This commit is contained in:
Bartłomiej Dach
2026-04-03 17:17:31 +02:00
committed by GitHub
Unverified
parent 796877a594
commit 090fe44f86
4 changed files with 21 additions and 111 deletions
@@ -331,7 +331,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
p.RequestResults = _ => resultsRequested = true;
});
AddUntilStep("wait for load", () => playlist.ChildrenOfType<DrawableLinkCompiler>().Any() && playlist.ChildrenOfType<BeatmapCardThumbnail>().First().DrawWidth > 0);
AddUntilStep("wait for load", () => playlist.ChildrenOfType<DrawableLinkCompiler>().Any()
&& playlist.ChildrenOfType<LinkFlowContainer>().First().ChildrenOfType<SpriteText>().Any()
&& playlist.ChildrenOfType<BeatmapCardThumbnail>().First().DrawWidth > 0);
AddStep("move mouse to first item title", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<LinkFlowContainer>().First().ChildrenOfType<SpriteText>().First()));
AddAssert("first item title not hovered", () => playlist.ChildrenOfType<DrawableLinkCompiler>().First().IsHovered, () => Is.False);
@@ -13,7 +13,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Graphics.Containers.Markdown;
using osu.Game.Graphics.Containers.Markdown.Footnotes;
using osu.Game.Overlays;
@@ -143,98 +142,11 @@ outdated: true # not sure about the format for ""list of mods"".
AddAssert("No notice box visible", () => !markdownContainer.ChildrenOfType<Container>().Any());
}
[Test]
public void TestAbsoluteImage()
{
AddStep("Add absolute image", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh";
markdownContainer.Text = "![intro](/wiki/images/Client/Interface/img/intro-screen.jpg)";
});
}
[Test]
public void TestRelativeImage()
{
AddStep("Add relative image", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/";
markdownContainer.Text = "![intro](../images/Client/Interface/img/intro-screen.jpg)";
});
}
[Test]
public void TestBlockImage()
{
AddStep("Add paragraph with block image", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/";
markdownContainer.Text = @"Line before image
![play menu](../images/Client/Interface/img/play-menu.jpg ""Main Menu in osu!"")
Line after image";
});
}
[Test]
public void TestInlineImage()
{
AddStep("Add inline image", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh";
markdownContainer.Text = "![osu! mode icon](/wiki/shared/mode/osu.png) osu!";
});
}
[Test]
public void TestTableWithImageContent()
{
AddStep("Add Table", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh";
markdownContainer.Text = @"
| Image | Name | Effect |
| :-: | :-: | :-- |
| ![](/wiki/images/shared/judgement/osu!/hit300.png ""300"") | 300 | A possible score when tapping a hit circle precisely on time, completing a Slider and keeping the cursor over every tick, or completing a Spinner with the Spinner Metre full. A score of 300 appears in an blue score by default. Scoring nothing except 300s in a beatmap will award the player with the SS or SSH grade. |
| ![](/wiki/images/shared/judgement/osu!/hit300g.png ""Geki"") | () Geki | A term from Ouendan, called Elite Beat! in EBA. Appears when playing the last element in a combo in which the player has scored only 300s. Getting a Geki will give a sizable boost to the Life Bar. By default, it is blue. |
| ![](/wiki/images/shared/judgement/osu!/hit100.png ""100"") | 100 | A possible score one can get when tapping a Hit Object slightly late or early, completing a Slider and missing a number of ticks, or completing a Spinner with the Spinner Meter almost full. A score of 100 appears in a green score by default. When very skilled players test a beatmap and they get a lot of 100s, this may mean that the beatmap does not have correct timing. |
| ![](/wiki/images/shared/judgement/osu!/hit300k.png ""300 Katu"") ![](/wiki/Skinning/Interface/img/hit100k.png ""100 Katu"") | () Katu or Katsu | A term from Ouendan, called Beat! in EBA. Appears when playing the last element in a combo in which the player has scored at least one 100, but no 50s or misses. Getting a Katu will give a small boost to the Life Bar. By default, it is coloured green or blue depending on whether the Katu itself is a 100 or a 300. |
| ![](/wiki/images/shared/judgement/osu!/hit50.png ""50"") | 50 | A possible score one can get when tapping a hit circle rather early or late but not early or late enough to cause a miss, completing a Slider and missing a lot of ticks, or completing a Spinner with the Spinner Metre close to full. A score of 50 appears in a orange score by default. Scoring a 50 in a combo will prevent the appearance of a Katu or a Geki at the combo's end. |
| ![](/wiki/images/shared/judgement/osu!/hit0.png ""Miss"") | Miss | A possible score one can get when not tapping a hit circle or too early (based on OD and AR, it may *shake* instead), not tapping or holding the Slider at least once, or completing a Spinner with low Spinner Metre fill. Scoring a Miss will reset the current combo to 0 and will prevent the appearance of a Katu or a Geki at the combo's end. |
";
});
}
[Test]
public void TestWideImageNotExceedContainer()
{
AddStep("Add image", () =>
{
markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/";
markdownContainer.Text = "![](../images/Client/Program_files/img/file_structure.jpg \"The file structure of osu!'s installation folder, on Windows and macOS\")";
});
AddUntilStep("Wait image to load", () => markdownContainer.ChildrenOfType<DelayedLoadWrapper>().First().DelayedLoadCompleted);
AddStep("Change container width", () =>
{
markdownContainer.Width = 0.5f;
});
AddAssert("Image not exceed container width", () =>
{
var spriteImage = markdownContainer.ChildrenOfType<Sprite>().First();
return Precision.DefinitelyBigger(markdownContainer.DrawWidth, spriteImage.DrawWidth);
});
}
[Test]
public void TestFlag()
{
AddStep("Add flag", () =>
{
markdownContainer.CurrentPath = @"https://dev.ppy.sh";
markdownContainer.Text = "::{flag=\"AU\"}:: ::{flag=\"ZZ\"}::";
});
AddAssert("Two flags visible", () => markdownContainer.ChildrenOfType<DrawableFlag>().Count(), () => Is.EqualTo(2));
@@ -5,6 +5,7 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.SongSelect
@@ -37,7 +38,11 @@ namespace osu.Game.Tests.Visual.SongSelect
WaitForFiltering();
AddAssert("select screen position unchanged", () => Carousel.ChildrenOfType<PanelBeatmap>().Single(p => p.Selected.Value).ScreenSpaceDrawQuad,
() => Is.EqualTo(positionBefore));
() => Is.EqualTo(positionBefore).Using<Quad, Quad>((expected, actual)
=> Precision.AlmostEquals(expected.TopLeft, actual.TopLeft)
&& Precision.AlmostEquals(expected.TopRight, actual.TopRight)
&& Precision.AlmostEquals(expected.BottomLeft, actual.BottomLeft)
&& Precision.AlmostEquals(expected.BottomRight, actual.BottomRight)));
}
[Test]
@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@@ -11,13 +9,11 @@ using osu.Framework.Audio;
using osu.Framework.Extensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Models;
using osu.Game.Online.API.Requests.Responses;
@@ -35,18 +31,17 @@ namespace osu.Game.Tests.Visual.UserInterface
{
public partial class TestSceneDeleteLocalScore : OsuManualInputManagerTestScene
{
private readonly ContextMenuContainer contextMenuContainer;
private readonly BeatmapLeaderboardWedge leaderboard;
private RulesetStore rulesets = null!;
private BeatmapManager beatmapManager;
private ScoreManager scoreManager;
private BeatmapManager beatmapManager = null!;
private ScoreManager scoreManager = null!;
private readonly List<ScoreInfo> importedScores = new List<ScoreInfo>();
private BeatmapInfo beatmapInfo;
private BeatmapInfo beatmapInfo = null!;
private LeaderboardManager leaderboardManager { get; set; }
private LeaderboardManager leaderboardManager { get; set; } = null!;
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
@@ -60,15 +55,11 @@ namespace osu.Game.Tests.Visual.UserInterface
{
Children = new Drawable[]
{
contextMenuContainer = new OsuContextMenuContainer
leaderboard = new BeatmapLeaderboardWedge
{
RelativeSizeAxes = Axes.Both,
Child = leaderboard = new BeatmapLeaderboardWedge
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(0.6f),
}
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(0.6f),
},
dialogOverlay = new DialogOverlay()
};
@@ -145,7 +136,7 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test]
public void TestDeleteViaRightClick()
{
ScoreInfo scoreBeingDeleted = null;
ScoreInfo scoreBeingDeleted = null!;
AddStep("open menu for top score", () =>
{
var leaderboardScore = leaderboard.ChildrenOfType<BeatmapLeaderboardScore>().First();
@@ -157,12 +148,12 @@ namespace osu.Game.Tests.Visual.UserInterface
});
// Ensure the context menu has finished showing
AddStep("finish transforms", () => contextMenuContainer.FinishTransforms(true));
AddStep("finish transforms", () => leaderboard.FinishTransforms(true));
AddStep("click delete option", () =>
{
InputManager.MoveMouseTo(contextMenuContainer.ChildrenOfType<DrawableOsuMenuItem>()
.First(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
InputManager.MoveMouseTo(leaderboard.ChildrenOfType<DrawableOsuMenuItem>()
.First(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
InputManager.Click(MouseButton.Left);
});