Stufe 4c (#764): Bezeichner auf Englisch - Typen, Methoden, Felder, Parameter, Locals, Testnamen
Mit Roslyn umbenannt (Verweise folgen, Zeichenketten bleiben unberuehrt). Nicht umbenannt, weil gespeichert oder ueber die API gebunden (Stufe 4e): Properties, Record-Parameter, Enum-Member sowie die Parameter der Endpunkt-Handler (Routen-/Query-Bindung ueber den Namen). Die JSON-Felder anonymer Objekte bleiben ausdruecklich benannt (JsonFilter: pfad). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
837a634a22
commit
77062facc9
@@ -14,7 +14,7 @@ public sealed class ChatMessageSerializationTests
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
[Fact]
|
||||
public void Ohne_Breakpoint_bleibt_der_Inhalt_ein_einfacher_String()
|
||||
public void Without_breakpoint_the_content_stays_a_plain_string()
|
||||
{
|
||||
var json = Serialize(ChatMessage.User("Hallo"));
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Nullwerte_werden_weggelassen()
|
||||
public void Null_values_are_omitted()
|
||||
{
|
||||
var json = Serialize(ChatMessage.Assistant("Antwort"));
|
||||
|
||||
@@ -31,7 +31,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToolAntwort_traegt_ihre_ToolCallId()
|
||||
public void Tool_answer_carries_its_ToolCallId()
|
||||
{
|
||||
var json = Serialize(ChatMessage.ToolResponse("call_42", "Ergebnis"));
|
||||
|
||||
@@ -39,7 +39,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AssistantMitToolCalls_serialisiert_die_Aufrufe()
|
||||
public void AssistantWithToolCalls_serialises_the_calls()
|
||||
{
|
||||
var msg = ChatMessage.AssistantWithToolCalls([
|
||||
new ToolCall { Id = "c1", Function = new ToolCallFunction { Name = "FileRW", Arguments = "{}" } }
|
||||
@@ -57,7 +57,7 @@ public sealed class ChatMessageSerializationTests
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
[Fact]
|
||||
public void Mit_Breakpoint_wird_der_Inhalt_zum_Block_mit_cache_control()
|
||||
public void With_breakpoint_the_content_becomes_a_block_with_cache_control()
|
||||
{
|
||||
var msg = ChatMessage.System("Du bist ein Agent.");
|
||||
msg.CacheBreakpoint = true;
|
||||
@@ -69,7 +69,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Der_Breakpoint_selbst_wird_nicht_als_Feld_serialisiert()
|
||||
public void The_breakpoint_itself_is_not_serialised_as_a_field()
|
||||
{
|
||||
var msg = ChatMessage.User("Text");
|
||||
msg.CacheBreakpoint = true;
|
||||
@@ -82,7 +82,7 @@ public sealed class ChatMessageSerializationTests
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
[Fact]
|
||||
public void Inhalt_als_String_wird_gelesen()
|
||||
public void Content_as_string_is_read()
|
||||
{
|
||||
var msg = Deserialize("""{"role":"assistant","content":"Antwort"}""");
|
||||
|
||||
@@ -91,7 +91,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Inhalt_als_Blockarray_wird_gelesen()
|
||||
public void Content_as_block_array_is_read()
|
||||
{
|
||||
// This is what a persisted context written with a breakpoint looks like.
|
||||
var msg = Deserialize(
|
||||
@@ -101,7 +101,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mehrere_Textbloecke_werden_zusammengefuehrt()
|
||||
public void Several_text_blocks_are_merged()
|
||||
{
|
||||
var msg = Deserialize(
|
||||
"""{"role":"user","content":[{"type":"text","text":"Teil A"},{"type":"text","text":" Teil B"}]}""");
|
||||
@@ -110,7 +110,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fehlender_Inhalt_wird_zu_null()
|
||||
public void Missing_content_becomes_null()
|
||||
{
|
||||
var msg = Deserialize("""{"role":"assistant","tool_calls":[]}""");
|
||||
|
||||
@@ -118,7 +118,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unbekannte_Felder_stoeren_nicht()
|
||||
public void Unknown_fields_do_no_harm()
|
||||
{
|
||||
var msg = Deserialize("""{"role":"user","content":"Text","reasoning":"…","annotations":[1,2]}""");
|
||||
|
||||
@@ -126,7 +126,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTrip_erhaelt_alle_Felder()
|
||||
public void RoundTrip_keeps_all_fields()
|
||||
{
|
||||
var original = ChatMessage.ToolResponse("call_7", "Das Ergebnis");
|
||||
|
||||
@@ -138,7 +138,7 @@ public sealed class ChatMessageSerializationTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTrip_erhaelt_Umlaute_und_Emoji()
|
||||
public void RoundTrip_keeps_umlauts_and_emoji()
|
||||
{
|
||||
var original = ChatMessage.User("Grüße aus München 🦀 — größer & schöner");
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public sealed class ModelPricingTests
|
||||
[InlineData("0.000015", 15.0)]
|
||||
[InlineData("0.0000001", 0.1)]
|
||||
[InlineData("0", 0.0)]
|
||||
public void Preise_pro_Token_werden_auf_eine_Million_hochgerechnet(string raw, double expected)
|
||||
public void Prices_per_token_are_scaled_to_one_million(string raw, double expected)
|
||||
{
|
||||
ModelPricing.ParsePerToken(raw).ShouldBe((decimal)expected);
|
||||
}
|
||||
@@ -31,13 +31,13 @@ public sealed class ModelPricingTests
|
||||
[InlineData("")]
|
||||
[InlineData("keine-zahl")]
|
||||
[InlineData("-0.001")]
|
||||
public void Unbrauchbare_Angaben_ergeben_null(string? raw)
|
||||
public void Unusable_values_give_null(string? raw)
|
||||
{
|
||||
ModelPricing.ParsePerToken(raw).ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Die_Umrechnung_ist_unabhaengig_von_der_Systemsprache()
|
||||
public void The_conversion_is_independent_of_the_system_language()
|
||||
{
|
||||
// With German culture "0.000003" would otherwise be read as 3 instead of 0.000003.
|
||||
var original = Thread.CurrentThread.CurrentCulture;
|
||||
@@ -57,7 +57,7 @@ public sealed class ModelPricingTests
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
[Fact]
|
||||
public void Preise_werden_aus_der_Modellantwort_gelesen()
|
||||
public void Prices_are_read_from_the_model_response()
|
||||
{
|
||||
var item = JsonDocument.Parse("""
|
||||
{ "id": "anthropic/claude-sonnet-4-5",
|
||||
@@ -76,7 +76,7 @@ public sealed class ModelPricingTests
|
||||
[InlineData("""{ "id": "x", "pricing": {} }""")]
|
||||
[InlineData("""{ "id": "x", "pricing": { "prompt": "0.000003" } }""")]
|
||||
[InlineData("""{ "id": "x", "pricing": "kostenlos" }""")]
|
||||
public void Unvollstaendige_Preisangaben_ergeben_null(string json)
|
||||
public void Incomplete_prices_give_null(string json)
|
||||
{
|
||||
// Half the information is worse than none — it would result in a plausible-looking
|
||||
// but wrong sum.
|
||||
@@ -100,7 +100,7 @@ public sealed class ModelPricingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Die_Kosten_werden_aus_Prompt_und_Completion_getrennt_berechnet()
|
||||
public void The_costs_are_calculated_separately_from_prompt_and_completion()
|
||||
{
|
||||
var catalog = CatalogWith(("anthropic/claude-sonnet-4-5", 3m, 15m));
|
||||
|
||||
@@ -112,7 +112,7 @@ public sealed class ModelPricingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ein_unbekanntes_Modell_wird_als_unbekannt_gemeldet_statt_als_null_Kosten()
|
||||
public void An_unknown_model_is_reported_as_unknown_instead_of_zero_cost()
|
||||
{
|
||||
// The core of the old error: 0 looked like free.
|
||||
var catalog = CatalogWith(("openai/gpt-4o", 2.5m, 10m));
|
||||
@@ -124,7 +124,7 @@ public sealed class ModelPricingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Grossschreibung_der_Modell_ID_spielt_keine_Rolle()
|
||||
public void Case_of_the_model_ID_does_not_matter()
|
||||
{
|
||||
var catalog = CatalogWith(("openai/gpt-4o", 2.5m, 10m));
|
||||
|
||||
@@ -132,7 +132,7 @@ public sealed class ModelPricingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Modelle_ohne_Preisangabe_landen_nicht_im_Katalog()
|
||||
public void Models_without_price_do_not_end_up_in_the_catalogue()
|
||||
{
|
||||
var catalog = new ModelPricingCatalog();
|
||||
catalog.Load([
|
||||
@@ -146,13 +146,13 @@ public sealed class ModelPricingTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ein_leerer_Katalog_kennt_kein_Modell()
|
||||
public void An_empty_catalogue_knows_no_model()
|
||||
{
|
||||
new ModelPricingCatalog().Estimate("beliebig", 1000, 100).IsKnown.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Erneutes_Laden_aktualisiert_die_Preise()
|
||||
public void Reloading_updates_the_prices()
|
||||
{
|
||||
var catalog = CatalogWith(("m", 1m, 2m));
|
||||
catalog.Load([new ModelInfo { Id = "m", Pricing = new ModelPricing(5m, 10m) }]);
|
||||
|
||||
@@ -26,7 +26,7 @@ public sealed class RetryPolicyTests
|
||||
[InlineData(HttpStatusCode.Forbidden, false)]
|
||||
[InlineData(HttpStatusCode.NotFound, false)]
|
||||
[InlineData(HttpStatusCode.Conflict, false)]
|
||||
public void Nur_voruebergehende_Stoerungen_werden_wiederholt(HttpStatusCode status, bool expected)
|
||||
public void Only_temporary_disruptions_are_retried(HttpStatusCode status, bool expected)
|
||||
{
|
||||
// A 400 or 401 does not repeat itself by itself — waiting for it
|
||||
// only delays the error message.
|
||||
@@ -34,7 +34,7 @@ public sealed class RetryPolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Die_Wartezeit_waechst_exponentiell()
|
||||
public void The_wait_time_grows_exponentially()
|
||||
{
|
||||
var policy = new RetryPolicy { BaseDelay = TimeSpan.FromSeconds(1), JitterFactor = 0 };
|
||||
|
||||
@@ -45,7 +45,7 @@ public sealed class RetryPolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Die_Wartezeit_ist_nach_oben_begrenzt()
|
||||
public void The_wait_time_is_capped()
|
||||
{
|
||||
var policy = new RetryPolicy
|
||||
{
|
||||
@@ -58,7 +58,7 @@ public sealed class RetryPolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ein_RetryAfter_des_Servers_hat_Vorrang()
|
||||
public void A_server_RetryAfter_takes_precedence()
|
||||
{
|
||||
var policy = new RetryPolicy { BaseDelay = TimeSpan.FromSeconds(1), JitterFactor = 0 };
|
||||
|
||||
@@ -66,7 +66,7 @@ public sealed class RetryPolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Auch_ein_RetryAfter_wird_gedeckelt()
|
||||
public void A_RetryAfter_is_capped_too()
|
||||
{
|
||||
// A server could demand hours — no run may block that long.
|
||||
var policy = new RetryPolicy { MaxDelay = TimeSpan.FromSeconds(30) };
|
||||
@@ -78,7 +78,7 @@ public sealed class RetryPolicyTests
|
||||
[InlineData(0.0)]
|
||||
[InlineData(0.5)]
|
||||
[InlineData(1.0)]
|
||||
public void Die_Streuung_bleibt_im_erwarteten_Rahmen(double sample)
|
||||
public void The_spread_stays_within_the_expected_range(double sample)
|
||||
{
|
||||
var policy = new RetryPolicy { BaseDelay = TimeSpan.FromSeconds(4), JitterFactor = 0.25 };
|
||||
|
||||
@@ -109,7 +109,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ein_RateLimit_beendet_den_Lauf_nicht_mehr()
|
||||
public async Task A_rate_limit_no_longer_ends_the_run()
|
||||
{
|
||||
var handler = new FakeHttpMessageHandler()
|
||||
.Responds(HttpStatusCode.TooManyRequests, """{"error":"rate limit"}""")
|
||||
@@ -124,7 +124,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Mehrere_Stoerungen_hintereinander_werden_ueberbrueckt()
|
||||
public async Task Several_disruptions_in_a_row_are_bridged()
|
||||
{
|
||||
var handler = new FakeHttpMessageHandler()
|
||||
.Responds(HttpStatusCode.ServiceUnavailable)
|
||||
@@ -139,7 +139,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Nach_dem_letzten_Versuch_wird_der_Fehler_gemeldet()
|
||||
public async Task After_the_last_attempt_the_error_is_reported()
|
||||
{
|
||||
var policy = new RetryPolicy { MaxAttempts = 3 };
|
||||
var handler = new FakeHttpMessageHandler()
|
||||
@@ -157,7 +157,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ein_dauerhafter_Fehler_wird_nicht_wiederholt()
|
||||
public async Task A_permanent_error_is_not_retried()
|
||||
{
|
||||
// A 401 does not get better by waiting — report immediately.
|
||||
var handler = new FakeHttpMessageHandler()
|
||||
@@ -172,7 +172,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Netzwerkfehler_werden_wiederholt()
|
||||
public async Task Network_errors_are_retried()
|
||||
{
|
||||
var handler = new FakeHttpMessageHandler()
|
||||
.Throws(new HttpRequestException("Verbindung abgebrochen"))
|
||||
@@ -186,7 +186,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ein_Abbruch_durch_den_Benutzer_wird_nicht_wiederholt()
|
||||
public async Task An_abort_by_the_user_is_not_retried()
|
||||
{
|
||||
var handler = new FakeHttpMessageHandler().Responds(HttpStatusCode.TooManyRequests);
|
||||
using var client = CreateClient(handler);
|
||||
@@ -201,7 +201,7 @@ public sealed class OpenRouterClientRetryTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Ein_erfolgreicher_erster_Versuch_loest_keine_Wiederholung_aus()
|
||||
public async Task A_successful_first_attempt_triggers_no_retry()
|
||||
{
|
||||
var handler = new FakeHttpMessageHandler().RespondsWithSuccess(SuccessBody);
|
||||
using var client = CreateClient(handler);
|
||||
|
||||
Reference in New Issue
Block a user