Pro-tip to any devs who only discovered TDD thanks to coding agents: refactoring is inherently directional. It's more like prefactoring—you rearrange code to make the next change easy. That means you (and your agent) should know the next planned change before you refactor!

@searls I wouldn't mind if the pre-factoring mode took precedence.

I take code refactoring as a close analogy to math, where you might re-compose terms of an expression to make the next operation easy.

The other reason to refactor isn't to make the next intended change easy, but to leave the code in a state that's more readable and less vulnerable to rot and confusion.

Factoring up common set-up in tests, and eliminating duplicate re-assertions across cases.

@jmeowmeow @searls
Yes, I'm with Jeff. TBF, sometimes I do "prefactor", certainly, but more often I'm just making the code more like code should be.

@RonJeffries @jmeowmeow @searls

The concept of removing the duplication between test and code was what made it click for me, and that's been the bulk of what I do during the refactoring step.

@orchun @jmeowmeow @searls
Hm, interesting. I don't often see much duplication of that kind, with the exception of occasional tests to figure out how some bit of the language works.

Are you kind of building up a function in the test and then moving/replicating it in the app?

@RonJeffries @jmeowmeow @searls
No, just getting to green super fast by putting in the app what the test expects.

Then replacing the result with computation is my "refactoring" step. Actual refactoring in the sense of design change follows, but only if I don't like how things look.

The "pre factoring" I typically only do if I can't figure out how to write a simple test.

@orchun @RonJeffries @jmeowmeow @searls
This is an interesting discussion from a UX Designer perspective.
Typically would design the ideal experience (golden thread/happy path) then affordances to guide/support people through implemented happy path (silver thread/learning path) & finally defensive experience for functional & system exceptions (red thread/unhappy path)
Majority of code is defensive (what to do when something unexpected happens) as ideal experience is usually straight forward.

@RonJeffries @orchun I tend to think of porting logic drafted in the test or test harness into the application as the Russ Rufer and Tracy Bialik TDD technique I encountered at the Silicon Valley Patterns Group.

I have seen a lot of duplication in test cases where new paths or variations are handled by copy-paste without factoring out common set-up or discarding redundant assertions.

@jmeowmeow @orchun
I don't much mind duplication in tests, tend to leave them alone when they work. Of course when I change prod things, sometimes tests must change.

@RonJeffries When I refactor a sequence of steps, and several dozen interaction tests break, often needing individual fixing, is an unpleasant experience which has shaped my attitude toward duplication in test cases.

(snipped: a tangent on alternative responses)

Orchestration logic appropriately uses interaction testing with mocks or other doubles. For domain logic, interaction testing isn't my first choice; input and output for representative domain examples is where I prefer to go.

@jmeowmeow yes. If that happened to me, I'd do the same.