test: remove trivial, duplicate and content-value tests (#2721)

## Summary
Many tests proved a specific change when it landed but don't need to run on every CI build forever. This removes **202 test methods and 9 files: 313 test cases, 2,247 → 1,934**. UOContent.Tests drops from about 14s to about 5s locally.

Removed:
- **Tautologies.** Asserting a constant, a constructor readback or a trivial getter, or testing BCL behavior.
- **Exact duplicates** of a surviving test on the same code path.
- **Obsolete regressions** whose failure can no longer be expressed.
- **Game-content values** shard owners customize (era drop rates, loot and skill tables, single-creature tuning). Each customization would otherwise force a test fix.

## How it was decided
1. Every test was classified, with a reason, by a per-shard sweep over all 287 test files.
2. Each proposed deletion was then checked by a second, adversarial reviewer against the surviving tests and the production code.
3. Anything that was the only coverage of a separate code path was **kept**, even where it looked like a duplicate. Examples: the unsigned `SpanReader`/`SpanWriter` methods, the at-location versus bounds enumerators, null-map enumerables, the security filters, archive-journal state transitions. About 130 proposed deletions were rejected this way.

Whole files removed:
- `FishingTests`, apart from 3 tests: the map-edge scan, serpent cleanup, and SOS chest consumption. The SOS test now stops at the first chest instead of measuring a catch rate. The multi-million-cast rate simulations are gone.
- `LordOaksTests` and `MeerEnragedTests` (single-creature tests).
- `AutoArchiveHelperTests`, `JsonDiscoverableTypeAttributeTests`, `DecimalSerializationTests` and `EnumConversionTests` (tautologies, or tests of their own local helpers).
- `NetworkStatsTests`.
- `MigratedDataLoadTests` (a subset of `AllSpawnFilesLoadTests`).
- `SpawnerFixtureCapture`: a capture tool, not a test, and its `version == 12` assert can no longer pass. The `.bin` fixtures it produced stay.

## Tests
- Server.Tests: 811 pass.
- UOContent.Tests: 1,123 pass.

A follow-up PR, stacked on this one, fixes how the remaining tests behave: shared state, CI-vacuous tests, harness duplication.
This commit is contained in:
Kamron Batman 2026-10-18 20:08:19 -07:00 • committed by GitHub
parent 078be52777
commit 9a25054809
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
89 changed files with 11 additions and 4603 deletions

View file

@ -54,15 +54,6 @@ namespace Server.Tests
Assert.Equal("Test ModernUO", result.Name);
}
[Fact]
public void TestTwoParamsOptionalActivator()
{
var result = typeof(TestTwoOptionalParamsClass).CreateInstance<TestTwoOptionalParamsClass>(10, "Prod ModernUO");
Assert.IsType<TestTwoOptionalParamsClass>(result);
Assert.Equal(10, result.Amount);
Assert.Equal("Prod ModernUO", result.Name);
}
private class TestZeroParamsClass
{
}

View file

@ -35,54 +35,6 @@ public class HtmlEscapeTests
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Multiple instances of same character")]
[InlineData("<><>", "&lt;&gt;&lt;&gt;")]
[InlineData("&&&&", "&amp;&amp;&amp;&amp;")]
[InlineData("\"\"\"", "&quot;&quot;&quot;")]
[InlineData("'''", "&#39;&#39;&#39;")]
[InlineData(">>>", "&gt;&gt;&gt;")]
public void EscapeHtml_MultipleSpecialCharacters_EscapesAll(string input, string expected)
{
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Mixed content")]
[InlineData("Hello <world>", "Hello &lt;world&gt;")]
[InlineData("<div>Hello</div>", "&lt;div&gt;Hello&lt;/div&gt;")]
[InlineData("Tom & Jerry", "Tom &amp; Jerry")]
[InlineData("He said \"hello\"", "He said &quot;hello&quot;")]
[InlineData("It's a test", "It&#39;s a test")]
public void EscapeHtml_MixedContent_EscapesMixedSpecialCharacters(string input, string expected)
{
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Starting with special character")]
[InlineData("<Hello", "&lt;Hello")]
[InlineData(">World", "&gt;World")]
[InlineData("&Start", "&amp;Start")]
[InlineData("\"Quote", "&quot;Quote")]
[InlineData("'Apostrophe", "&#39;Apostrophe")]
public void EscapeHtml_StartsWithSpecialCharacter_EscapesStart(string input, string expected)
{
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Ending with special character")]
[InlineData("Hello<", "Hello&lt;")]
[InlineData("World>", "World&gt;")]
[InlineData("End&", "End&amp;")]
[InlineData("Quote\"", "Quote&quot;")]
[InlineData("Test'", "Test&#39;")]
public void EscapeHtml_EndsWithSpecialCharacter_EscapesEnd(string input, string expected)
{
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Complex mixed scenarios")]
[InlineData("<p>Hello & goodbye</p>", "&lt;p&gt;Hello &amp; goodbye&lt;/p&gt;")]
[InlineData("&lt;already&gt;", "&amp;lt;already&amp;gt;")]
@ -103,59 +55,6 @@ public class HtmlEscapeTests
Assert.Empty(result);
}
[Fact(DisplayName = "Empty string input")]
public void EscapeHtml_EmptyString_ReturnsEmpty()
{
var result = "".EscapeHtml();
Assert.Empty(result);
}
[Fact(DisplayName = "Only special characters")]
public void EscapeHtml_OnlySpecialCharacters_EscapesAll()
{
const string input = "<>&\"'";
const string expected = "&lt;&gt;&amp;&quot;&#39;";
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Fact(DisplayName = "Ampersand must be escaped first")]
public void EscapeHtml_AmpersandFirst_PreventDoubleEscaping()
{
// This is critical: & must be escaped to &amp;
// If we're not careful, we could double-escape already-escaped content
const string input = "&lt;";
const string expected = "&amp;lt;";
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "ReadOnlySpan overload - no special characters")]
[InlineData("Hello World")]
[InlineData("Plain text")]
public void EscapeHtml_ReadOnlySpan_NoSpecialCharacters_ReturnsUnchanged(string input)
{
var result = input.AsSpan().EscapeHtml();
Assert.Equal(input, result);
}
[Theory(DisplayName = "ReadOnlySpan overload - with special characters")]
[InlineData("<div>", "&lt;div&gt;")]
[InlineData("Tom & Jerry", "Tom &amp; Jerry")]
public void EscapeHtml_ReadOnlySpan_WithSpecialCharacters_EscapesCorrectly(string input, string expected)
{
var result = input.AsSpan().EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "ReadOnlySpan overload - empty input")]
[InlineData("")]
public void EscapeHtml_ReadOnlySpan_Empty_ReturnsEmpty(string input)
{
var result = input.AsSpan().EscapeHtml();
Assert.Empty(result);
}
[Fact(DisplayName = "Consecutive special characters")]
public void EscapeHtml_ConsecutiveSpecialCharacters_EscapesAll()
{
@ -165,51 +64,6 @@ public class HtmlEscapeTests
Assert.Equal(expected, result);
}
[Fact(DisplayName = "Special characters with single normal character between")]
public void EscapeHtml_SpecialCharactersWithGaps_EscapesAll()
{
const string input = "<a>b&c\"d'e";
const string expected = "&lt;a&gt;b&amp;c&quot;d&#39;e";
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Fact(DisplayName = "HTML tags")]
public void EscapeHtml_HtmlTags_EscapesTagBrackets()
{
var input = "<html><body>Hello</body></html>";
var expected = "&lt;html&gt;&lt;body&gt;Hello&lt;/body&gt;&lt;/html&gt;";
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Fact(DisplayName = "HTML attributes with mixed quotes")]
public void EscapeHtml_HtmlAttributesWithQuotes_EscapesCorrectly()
{
var input = "<a href=\"test\" data='value'>";
var expected = "&lt;a href=&quot;test&quot; data=&#39;value&#39;&gt;";
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Theory(DisplayName = "Whitespace handling")]
[InlineData(" spaces ", " spaces ")]
[InlineData("\ttabs\t", "\ttabs\t")]
[InlineData("\nnewlines\n", "\nnewlines\n")]
public void EscapeHtml_Whitespace_PreservedAsIs(string input, string expected)
{
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Fact(DisplayName = "Performance: long string without special characters")]
public void EscapeHtml_LongStringNoSpecialCharacters_ReturnsQuickly()
{
var input = new string('a', 10000);
var result = input.EscapeHtml();
Assert.Equal(input, result);
}
[Fact(DisplayName = "Performance: long string with special characters")]
public void EscapeHtml_LongStringWithSpecialCharacters_HandlesCorrectly()
{
@ -229,15 +83,4 @@ public class HtmlEscapeTests
var result = input.EscapeHtml();
Assert.Equal(expected, result);
}
[Fact(DisplayName = "String overload matches ReadOnlySpan overload")]
public void EscapeHtml_StringVsReadOnlySpan_ProduceSameResult()
{
const string input = "<div>Tom & Jerry 'in' \"quotes\"</div>";
var resultString = input.EscapeHtml();
var resultSpan = input.AsSpan().EscapeHtml();
Assert.Equal(resultString, resultSpan);
}
}

View file

@ -7,17 +7,6 @@ namespace Server.Tests;
[Collection("Sequential Server Tests")]
public class TestStringHelpers
{
[Theory]
[InlineData(null, "default value", "default value")]
[InlineData("", "default value", "default value")]
[InlineData("this is a valid string", "default value", "this is a valid string")]
public void TestIsNullOrDefault(string value, string defaultValue, string expected)
{
var actual = value.DefaultIfNullOrEmpty(defaultValue);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData("this is not capitalized", "This Is Not Capitalized")]
[InlineData("", "")]