behavior-preserving-refactor
Skill1.1k starsChanged 23 days agoMITView on GitHub
Preserve observable behavior when splitting files, moving members, consolidating helpers, or simplifying TestFx code. Use for structural refactors and file-diet implementation; inventory baseline semantics and consumers, then run focused equivalence checks.
We split this skill into the rules it gives an agent
15 rules. About 0 are common, 11 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈11
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 8
Use this recipe for the specific code being refactored, not a repository-wide audit.
- Distinctive: line 17
Do not claim equivalence, tested behavior, or complete consumer coverage from that sample.
- Distinctive: line 36
Do not add support for impossible states, but do not assume compiler or user input is always valid: analyzer inputs can be incomplete or …
- Distinctive: line 39
Use existing behavior as the oracle, not the intended behavior of a new helper.
- Distinctive: line 44
Check initialization order if moving fields between partial files.
- Very specific: line 49
Keep target frameworks, conditional compilation, supported platforms, and package layout intact.
- Very specific: line 52
Check applicable PublicAPI and InternalAPI shipped/unshipped baselines.
- Distinctive: line 53
Prefer unchanged signatures and accessibility.
- Distinctive: line 63
Before consolidating helpers, compare every caller's baseline.
- Distinctive: line 69
Do not replace a loop with a dictionary, eager projection, sort, or single-match operator without proving duplicate handling, enumeration, …
- Distinctive: line 75
If the size target requires behavior changes or unsafe fragmentation, stop that part of the refactor and report the remaining line count …
- Distinctive: line 77
Do not alter semantics just to meet a file-size goal.
- Distinctive: line 99
Before editing, run the existing focused checks when feasible and add any necessary distinguishing cases against the original …
- Very specific: line 104
Use the repo-local toolchain and documented filtered build/test commands from .github/copilot-instructions.md.
- Distinctive: line 109
If shipping package/source inclusion changes, validate the packed consumer layout using existing acceptance infrastructure.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Behavior-Preserving Refactors
Use this recipe for the specific code being refactored, not a repository-wide
audit. Read .github/copilot-instructions.md and applicable directory rules.
Preserve existing behavior, including surprising reachable cases; a bug fix or
modernization needs separate authorization and validation.
An issue-generation workflow's bounded inspection is not implementation preflight. For example, Daily File Diet inspects only the first 100 lines and up to 50 declaration lines of one file. Keep that budget when proposing work, label unverified assumptions, and include this recipe for the later implementer. Do not claim equivalence, tested behavior, or complete consumer coverage from that sample.
1. Establish the baseline before editing
Identify the exact methods or declarations to move or extract, their callers, existing focused tests, and owning projects. Read the complete affected bodies and relevant context, not just signatures or similar-looking helpers. For each existing implementation that might share a helper, record:
| Boundary | What must remain unchanged |
| Selection | Iteration order, first versus last match, first matching name versus first matching typed value, exact type tests, casts, defaults, and missing-value handling. |
| Evaluation | Short-circuit operand order, which callbacks run and how often, enumeration count, laziness, mutation, and side effects before return or failure. |
| Results and failures | Return values, diagnostics and locations, output ordering, exception type and timing, cancellation, and cleanup/disposal order where affected. |
| Compilation | Namespaces, accessibility, attributes, overload binding, target-framework guards, and native interop signatures and marshalling. |
| Cost | Allocations, materialization, boxing, repeated scans, and algorithmic complexity on affected hot paths. |
Inventory reachable empty, duplicate, malformed, null, and wrong-type inputs. Do not add support for impossible states, but do not assume compiler or user input is always valid: analyzer inputs can be incomplete or contain errors. Name the existing guard that makes a case unreachable if excluding it. Use existing behavior as the oracle, not the intended behavior of a new helper.
2. Trace the actual consumers and constraints
- Find all partial declarations and call sites of the affected type or member. Check initialization order if moving fields between partial files.
- Inspect owning project files and imports for linked
Compileitems, shared source, globs, explicit includes, and packaging rules. Find every consuming project, including source-only packages; a build of the original owner does not prove that a new file is included by another consumer. - Keep target frameworks, conditional compilation, supported platforms, and
package layout intact. A native interop file move is not permission to replace
DllImport, change marshalling, or adopt APIs unavailable on older targets. - Check applicable
PublicAPIandInternalAPIshipped/unshipped baselines. Prefer unchanged signatures and accessibility; do not expose a helper just to share it. Record required newly tracked declarations without rewriting shipped API history.
3. Make the structural change, not adjacent cleanup
Move existing bodies unchanged first, preserving attributes, guards, resource access, and file encoding. Keep unrelated renaming, formatting, LINQ rewrites, interop modernization, new validation, and behavior fixes out of the change.
Before consolidating helpers, compare every caller's baseline. Similar names or happy-path outputs do not establish equivalence. If callers differ in selection, evaluation, or failure behavior, keep separate implementations or use the smallest explicit helper that preserves each contract; do not invent a configurable abstraction merely to eliminate duplication.
Do not replace a loop with a dictionary, eager projection, sort, or single-match operator without proving duplicate handling, enumeration, and failure behavior. On hot paths, preserve allocation and complexity characteristics. Use existing allocation/performance checks when the extraction could change them; do not introduce a benchmark project for a pure move.
If the size target requires behavior changes or unsafe fragmentation, stop that part of the refactor and report the remaining line count and concrete constraint. Do not alter semantics just to meet a file-size goal.
4. Use distinguishing equivalence cases
These are examples to adapt to the actual baseline, not new product semantics:
| Baseline | Focused case | Required observation |
| A loop overwrites its result for every matching name. | Matching values 1, then 2. | Result remains 2; returning the first match is not equivalent. |
A loop returns the first matching name whose value is an int. | Same-name string "bad", integer 7, then integer 9. | Result remains 7; taking the first name then casting, or taking the last integer, is not equivalent. |
Exact int type matching. | Same-name long value 7L, followed by int value 8. | Result remains 8; numeric conversion changes type selection. |
ShouldRun() && Execute(). | ShouldRun returns false; Execute records a call or throws. | Only ShouldRun runs; reordering operands or evaluating both eagerly is not equivalent. |
| A guarded interop declaration moves to another file. | Build every source-linked consumer and affected supported TFM/platform path. | Declaration, guards, accessibility, and marshalling remain unchanged; no new runtime API requirement. |
Also cover the actual missing/empty and malformed-only outcomes, not just malformed input followed by a valid value. Assert observable values, diagnostic locations, exception behavior, and ordered side-effect traces where applicable. Pin expectations to the baseline; comparing two paths that both call the new helper is not an equivalence test.
5. Validate the smallest relevant surface
Before editing, run the existing focused checks when feasible and add any necessary distinguishing cases against the original implementation. After the change, rerun the same checks. Explain pre-existing failures or unavailable checks; do not report unrun checks as passed.
Use the repo-local toolchain and documented filtered build/test commands from
.github/copilot-instructions.md. Build the owning and linked consuming
projects for affected target frameworks. Run directly related tests, escalating
only when dependencies or failures justify it. A pure file move needs inclusion
and compilation checks plus relevant existing tests, not the full solution.
If shipping package/source inclusion changes, validate the packed consumer
layout using existing acceptance infrastructure.
Review the final diff for changed expressions, ordering, signatures, attributes, guards, includes, tracked APIs, and unintended adjacent edits. Measure resulting file sizes rather than assuming the split meets its target.
Completion evidence
Report the moved/extracted responsibility, baseline invariants and distinguishing cases, affected consumers/TFMs and API surfaces, exact checks and outcomes, and resulting line counts when size is the goal. Identify any remaining uncertainty or blocked target explicitly. Compilation alone does not prove runtime equivalence, and passing happy-path tests does not settle first/last selection or short-circuit behavior.
Trending
Quiet since September.about the whole repository
Who's talking about microsoft/testfx
- Stack Overflow“App.config not being loaded in .Net Core MSTests project”Stack Overflow · Feb 24, 2019 · 35 votes
- Stack Overflow“Visual Studio Test Explorer doesn't run tests after changes”Stack Overflow · Dec 21, 2022 · 31 votes
- Stack Overflow“DataTestMethod vs TestMethod”Stack Overflow · Dec 3, 2019 · 19 votes
- Stack Overflow“ConfigurationManager.AppSettings is always empty”Stack Overflow · May 5, 2020 · 17 votes
- dotnet/sdk“[Proposal]: Add Microsoft.NET.Sdk.Testing”GitHub · Jun 7, 2025 · 10 reactions
The biggest 5 of 68 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 68
Talked about on GitHub and Stack Overflow (68 times).
On GitHub · 41
- Jun 7, 2025[Proposal]: Add Microsoft.NET.Sdk.Testing — dotnet/sdksays it tested it10 reactions · 15 comments
- Feb 4, 2025Dependabot job fails due to attempt to update packages referenced via an MSBuild SDK — dependabot/dependabot-core9 reactions · 13 comments
- Feb 22, 2024Microsoft Testing Platform for xUnit — xunit/visualstudio.xunitsays it tested it6 reactions · 19 comments
- Dec 3, 2018DataTestMethod vs TestMethod — microsoft/testfx-docs6 reactions · 4 comments
- Feb 19, 2024Microsoft Testing Platform for NUnit — nunit/nunit3-vs-adaptersays it tested it5 reactions · 1 comment
36 more on GitHub
- Dec 19, 2023Arcade should opt into `BuildWithNetFrameworkHostedCompiler` by default — dotnet/arcade5 reactions · 18 comments
- Nov 24, 2025Native support for Microsoft.Testing.Platform? — danielpalme/ReportGeneratorsays it tested it4 reactions · 3 comments
- Oct 31, 2025Selecting test runner without global.json — dotnet/sdk3 reactions · 2 comments
- Jul 15, 2025[Analyzer Proposal]: Don't use `stringBuilder.Append(new string(c, repeatCount))` — dotnet/runtime3 reactions · 3 comments
- Jul 13, 2025Allow `dotnet test --list-tests json` — dotnet/sdk3 reactions · 7 comments
- Jul 9, 2025Improve output of `dotnet test` with MTP — dotnet/sdk3 reactions · 6 comments
- Jan 30, 2024Support for the new test runner — nunit/nunit3 reactions · 3 comments
- Oct 17, 2017[ExcludeFromCodeCoverageAttribute] should be applicable to assemblies — dotnet/runtime3 reactions · 12 comments
- Sep 2, 2026chore(deps): update mstest to 4.4.0 — thomhurst/TUnit2 reactions · 3 comments
- Dec 17, 2025[MTP] Cannot switch off terminal logger when building during dotnet test — dotnet/sdk2 reactions
- Oct 8, 2025Bump MSTest.TestFramework from 3.11.0 to 4.0.0 — files-community/Files2 reactions · 1 comment
- May 27, 2025Dependabot Ignores Configuration File Settings in latest Version — dependabot/dependabot-core2 reactions · 7 comments
- May 20, 2025Add `-vs` and `-vscode` to build scripts — dotnet/arcade2 reactions · 8 comments
- Mar 14, 2025Add template for dotnet.config to dotnet new — dotnet/sdk2 reactions · 2 comments
- Jan 16, 2024An Allure adapter for MSTest — allure-framework/allure-csharp2 reactions · 2 comments
- Apr 10, 2018Added docs for dynamic data display name — microsoft/testfx-docs2 reactions · 1 comment
- Sep 3, 2026chore(deps): update microsoft.testing — thomhurst/TUnit1 reaction · 3 comments
- Mar 16, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/FAnsiSql1 reaction
- Mar 16, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/libarchive.net1 reaction
- Mar 16, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/RDMP1 reaction
- Mar 16, 2026sdk(deps): Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/CsvHandler1 reaction · 1 comment
- Mar 16, 2026chore(deps): bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/SharpDicom1 reaction
- Mar 16, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/nccid1 reaction
- Mar 15, 2026chore(deps): bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/filestats1 reaction
- Mar 15, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/MCPsharp1 reaction
- Mar 15, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/SynthEHR1 reaction
- Mar 15, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/TypeGuesser1 reaction
- Mar 15, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/LineReader1 reaction
- Mar 15, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/DicomTypeTranslation1 reaction
- Mar 12, 2026Bump dotnet-sdk from 10.0.103 to 10.0.201 — jas88/dcm2csv1 reaction
- Mar 11, 2026chore(deps): bump dotnet-sdk from 10.0.103 to 10.0.200 — jas88/PACSify1 reaction
- Mar 7, 2025Use Microsoft Testing Platform — martincostello/alexa-london-travelsays it tested it1 reaction · 3 comments
- Feb 17, 2025Bump the mstest group across 1 directory with 2 updates — kusl/fluentassertions1 reaction · 9 comments
- May 25, 2026Bump MSTest.TestAdapter and MSTest.TestFramework — fluentassertions/fluentassertions0 reactions · 8 comments
- May 18, 2026Bump the mstest group with 2 updates — fluentassertions/fluentassertions0 reactions · 3 comments
- May 11, 2026Bump MSTest.TestAdapter and MSTest.TestFramework — fluentassertions/fluentassertions0 reactions · 4 comments
On Stack Overflow · 27
- Feb 24, 2019App.config not being loaded in .Net Core MSTests project35 votes
- Dec 21, 2022Visual Studio Test Explorer doesn't run tests after changes31 votes
- Dec 3, 2019DataTestMethod vs TestMethod19 votes
- May 5, 2020ConfigurationManager.AppSettings is always empty17 votes
- Dec 4, 2020The type or namespace name 'PrivateObject' could not be found6 votes
22 more on Stack Overflow
- Nov 2, 2018'TestContext' does not contain a definition for 'DataRow'5 votes
- Jun 15, 2019Get TestResult in MSTest TestCleanup in C#4 votes
- Nov 14, 2024Does a [TestMethod] have to be public? What consequences are there if it isn't?3 votes
- Aug 26, 2020'Inconclusive' tests are reported as 'not run' by Azure DevOps3 votes
- Sep 18, 2018Guidance for running tests using MSTest v1 in Visual Studio 2017 15.8.13 votes
- Nov 29, 2017Long running unit test marked as passed fails TFS build - Object 'xxx.rem' has been disconnected or does not exist at the server.**3 votes
- Jun 25, 2021use PrivateObject in .net 5 from nugget MSTest.TestFramework2 votes
- Jan 7, 2020MS Test V2 - ClassInitialize behavior when fail2 votes
- Oct 30, 2019Test Methods and Test Class in compiled DLL2 votes
- Jan 15, 2019Use configuration file to specify connection string to define a data source in unit test2 votes
- May 2, 2017Where is MSTest V22 votes
- Oct 15, 2022How to unit test private method in .Net Core application which does not support "PrivateObject"1 vote
- Oct 5, 2022Only first DataRow gets executed in MSTest1 vote
- Feb 4, 2021MS Tests DataTestMethod Timeout for a single test1 vote
- Feb 13, 2020PrivateObject class not found in .Net Core 2.01 vote
- Jan 4, 2020MsTest TestCleanup method not called when an unhandled exception is thrown1 vote
- May 3, 2019Where do I find TestContext.AddResultFile()?1 vote
- Apr 24, 2017Inherited test class from generic base is ignored in MSTest1 vote
- Aug 20, 2025Use MSTest.Sdk for TestHelper0 votes · 1 answer
- Mar 9, 2022Test results are published correctly but not reflected in pipeline Results - Azure devops (Yaml)0 votes
- Dec 22, 2021Testing with empty string using DataRow in MsTestV20 votes
- Feb 6, 2018Why does Visual Studio Always pull in the latest version Unit Test Framework within a solution when older versions are already included0 votes
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- manman1414/frontend-refactor-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository62 other files it gives its agents.
- AGENTS.mdAGENTS.md
- eng/common/AGENTS.mdAGENTS.md
- .github/copilot-instructions.mdCopilot instructions
- assertion-qualitySkill
- binlog-failure-analysisSkill
- binlog-generationSkill
- build-parallelismSkill
- build-perf-baselineSkill
- build-perf-diagnosticsSkill
- check-bin-obj-clashSkill
- code-testing-agentSkill
- code-testing-extensionsSkill
- code-testingSkill
- copy-to-output-directorySkill
- coverage-analysisSkill
- crap-scoreSkill
- csharp-expertSkill
- csharp-refactoringSkill
- curation-exceptionsSkill
- detect-static-dependenciesSkill
- directory-build-organizationSkill
- eliminate-redundant-restoresSkill
- eval-performanceSkill
- extension-pointsSkill
- filter-syntaxSkill
- find-untested-sourcesSkill
- generate-testability-wrappersSkill
- grade-testsSkill
- including-generated-filesSkill
- incremental-buildSkill
- item-managementSkill
- migrate-static-to-wrapperSkill
- msbuild-antipatternsSkill
- msbuild-modernizationSkill
- msbuild-serverSkill
- msbuildSkill
- mtp-hot-reloadSkill
- platform-detectionSkill
- property-patternsSkill
- resolve-project-referencesSkill
- run-testsSkill
- scaffold-dotnet-test-projectSkill
- setup-local-sdkSkill
- target-authoringSkill
- testability-obstacleSkill
- test-analysis-extensionsSkill
- test-anti-patternsSkill
- test-gap-analysisSkill
- test-smell-detectionSkill
- test-taggingSkill
- test-value-evidenceSkill
- troubleshoot-binlog-mcpSkill
- writing-mstest-testsSkill
- agentic-workflowsSkill
- code-reviewSkill
- feature-deliverySkill
- post-release-activitiesSkill
- session-delivery-hygieneSkill
- testfx-acceptance-validationSkill
- testfx-localization-validationSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

