TCR is an alternative workflow of TDD that Kent Beck has been writing about and discussing recently. But what is it? What’s it feel like to use? How do you do it? In this interview, we talk with Thomas Deniffel about this, and about his experiences with it so far.


Transcript for episode 68 of the Test & Code Podcast

This transcript starts as an auto generated transcript.
PRs welcome if you want to help fix any errors.


Welcome to Test and Code, a podcast about software development, software testing, and Python.

With conventional test driven development, you write a failing test, get it to pass, then refactor, then run the test again to make sure that your refactoring didn’t break anything. But what if it did break something? Kent Beck has been recommending that people commit their code to revision control after every green test is run, so that you don’t lose that good code if you break something Oddman. Strom suggested a symmetrical idea to go ahead and revert the code when the tests fail. Kent writes that he hated the idea but had to try it, and then he wrote about it last September. And now we have TCR, Test and Commit or Revert. What does it feel like to actually do this? Well, Thomas DennisL has been using it since about a month after that article came out. In this episode, we’ll hear from Thomas about his experience with it. It’s a fascinating idea. Have a listen and let me know what you think.

Thank you to PyCharm for sponsoring this episode. Of course, I use PyCharm when developing and debugging tests. I use a lot of parameterization in order to have fewer tests cover more cases, and PyCharm has the absolute best support for pytest parameterization over any other editor hands down. However, I’ve also been using talks a lot to make sure my projects work on several Python versions and some different library versions. Pycharm can run talks. Also, I usually just right click on the talks any file in the project tree and hit run talks. If a test fails on one of the environments, I can see the test results and look at the failing test. Maybe set a Breakpoint and rerun the talks environment through the debugger all within pie chart. Try it out yourself by going to Test and code. Compychar. That link will give you four months to try out PyCharm Pro, but don’t wait. Save time now with PyCharm.

Today on Test and Code with me, I have Thomas Dennis and he’s joining me from Southern Germany. The topic at hand is a crazy wacky idea called TCR or test and Commit or Revert.

Am I saying that right?

Yes, that’s right. Test, commit, revert. But the special characters between are important as it is a unique style command and it’s basically if tests are green, then commit otherwise revert.

Okay, before we jump into that part, will you introduce yourself who you are, what you do, that sort of thing?

Yes. I’m Thomas Denver, and as you said, I’m from Germany.

I work as programmer for Money for about ten years or so.

In the past, I was heavily in the tester and development community and XP community, and at work I created traditionally enterprise software for customers. But a year ago I focused on the development of autonomous drones in our company.

I started a company a few years ago, and this is the way the company took and so I took it with the company and this was my path in the past. And in October, I think I read about this new thing, TCR, and I tried it and I used it constantly since then. And I always thought that many different programmers will use it immediately. But it happened that I don’t know of much that use TCR. And so I give regularly talks and workshops these days about TCR.

Okay, cool. So you do speak about it then and do workshops?

Yes, at local meetups. Okay.

Not professionally yet, but for free and for free pizza and beer.

Okay. Well, I’d buy you a beer if I could. Maybe next time I’m in Munich, we can meet up.

Sure.

You actually started like right out. The first time I noticed it was Kent Beck wrote about it in the end of September last year. So you really started right away?

Yes. It was a little bit luck because I detected this new platform, medium where you can publish blog posts and stuff, and only few people were there and that came back was there. So I followed him on his articles and I got immediate notifications when this article came out. And I bookmarked it back then. And after a few days I gave it a look and I was curious and had a day off of work. And so I tried it and got stuck with it.

And then you wrote an article in November on Medium as well. Same platform with some cute little robot. I like this.

Your article is TCR, how to Use It and alternative to TDD. Question Mark. You said you were familiar with TDD before you came into TCR. Was TDD something you had been using before?

Yes, for a few years. And this is how I developed software the past years. And the whole company does TGD. So we have the best practices already or we had it already.

Okay, so the TCR part is I’m not going to jump into TDD too much because I want to get into this TCR thing.

It’s so new and I don’t know enough about it to even ask questions. So how do you describe it and what’s the workflow like and pros and cons and all that stuff? So how do we get into this?

Yes, it’s kind of a special type of thing to describe because you can give a two minute introduction and can talk for hours about implications, which brings TCR stands for as you mentioned in the beginning, for tests. Commit Revert and if test green, then commit the code as revert the code.

And when you do TCR, you place your normal test command where you ask the system if your test suit is green, you replace it with this TCR script. It’s just a simple bash script when you create a prototype, then as soon as your test and code tests are green, your code gets always committed.

The revert command, on the other hand kicks in when your test is read if there’s a single failing unit test, for example, and reverts your code back to the last time when your code was committed and the last commit happened when your code was in a green state. Therefore it brings you automatically back to a green state as soon as you have a red test suit.

This reverting leads to an interesting change how you write code. Every mistake inviting your code leads to deletion of the wrong code because this reversion of the TCR command kicks in when you start this. This is quite frustrating in the beginning, but after some time you change your behavior and how you approach problems. So you don’t handle problems like before when you do TDD or just without test. But you begin to write very minimal and focus test and code write just enough production codes to make this very tiny test pass.

After you have written some production codes with this technique, you’re normally reflected to a more general solution.

You make this very tiny steps because whenever you write too much production code at once, you take a big bet because for example, you have written now ten lines of production code and it’s very likely that you made a little mistake. And if you didn’t create a test between the ten lines, all the ten lines gets reverted at once.

So normally after the first two or three deletions you start to write very minimal tests with very minimal production code changes.

And this is a good thing because TDD says to us that we should do baby steps and we should do fake it until they make it.

And TCR takes a step further and really motivates you to do this because otherwise you take this bet and normally you lose and you lose your source code.

So TCR puts you in the direction of the best practice that you already know from TDD. This is creating small and focused tests, for example, fake behavior as I mentioned, and from the fakes reflected towards a general solution.

First question is the first time I run my test I expect it to fail because I haven’t read any production code yet.

Yes, this is something that changes when you change from TDD to TCR. With TD, you normally write a failing unit test and then execute the test student. See if the test fails. Sure it fails and then you fix it. With TCR you write a failing unit test with some fake implementation together. So for example you have Fibonacci of one and then you create the function for Fibonacci and just return one.

So you build up your fake implementation more and more, which is very specialized to the input argument. And then when you do a refactoring step, you generalize the solution up to the point where you have the real algorithm implemented.

Okay, so you’re building up the tests in little tiny steps as well.

Yes.

Okay.

Both together.

And the difference to TDD is that TCR is an always screen technique like refactoring. There you want to stay always clean as well. And with TDD, as I mentioned, you start with a failing unit test and you are in a red step in the red state and want to go to the green state. With TCR you write your test and you fake implementation together and you stay in the green state of your source code.

Because TCR and refactoring both are green green techniques where you always want to stay in green. They fit very well together and therefore normally when you write code you always try to do as less as possible and shift everything to the refactoring because there you don’t have this mismatch between red and green and you can easily refactor them.

It’s joyful to refactor with TCR.

Sounds like it’s pushing most of the pushing more and more of the development time to the refactor stage then yes.

I think it’s a good thing because then you can think about your application in a broader scope because you don’t have to type and think about the system at once. But you can give some examples and then try to find general solution.

Okay, now you said you’ve been using this all the time. Now.

I try to. There are some projects where it makes no sense. I think they are aligned with the projects where TCD makes no sense because for example, I’ve created websites in the past with TCR and for the whole HTML and CSS stuff you can’t test much and if you create some tests for HTML it doesn’t really make sense. So TCR does not make sense. So I think there is no project where TCR would make sense where TV wouldn’t make sense. So TD is a prerequisite of TCR.

And also I mentioned before that I created autonomous drones and the project is written in C plus plus and has relatively high build and test times because C plus plus takes a while to compile and then TCR isn’t funny because you always have to wait for a minute or so. That TCR works and with TCR isn’t a big problem because you hit the run the test button and then you just continue coding and after 1 minute there’s some feedback. The TCR is differently because it would revert your code after 1 minute. So you really have to wait until you have the feedback and then it doesn’t make sense. So prerequisite is definitely that your project has a very short build and test time.

Yeah, okay. Or at least the build time is something.

It’s going to have to be either instantaneous or no build and then the test time. But for some projects, even if the entire suite takes a while, you could have a focused test suite where you’re just focusing on a subset of the tests that are fast.

Yes, this is a little bit open question I had a great discussion on after workshop which test to execute with TCR, because in principle you never want to slip to a red state, but if you run just single tests or so, you could go to a red state without knowing it and without TCR knowing it. So I think the practical solution is to run focus tests, but I think the idea of TCR is that the system as whole is in a clean state.

But I’m aware that this isn’t practical these days on a project that isn’t just a play project.

Yeah, that makes sense. Every project is different, but I could see something like this being a tool that you can use not all the time, but off and on, even in projects where it doesn’t make sense in tone. Is that pretty surprising at first when you get your code deleted on you?

Yes, it’s very surprising and very frustrating as well, because you have built your patterns how to approach a problem, and then TCR always kicks in and deletes your code, and then after you got used to it, you forget it and then TCR kicks in again and delete your code. And for example, I’ve written in one step way too much HTML and CSS code and together with the test and everything was reverted.

So it’s surprising in the beginning and kind of frustrating, which I think led to many negative comments on Reddit Earned or Hacker News about TCR, because I think many programmers don’t like the thought that their source code, their aircraft source code gets deleted by a tool.

But as I read through the comments, I’m quite sure that nearly nobody actually tried TCR before writing the comments. So I think you have to get used to it for, I don’t know, one or 2 hours at least, or maybe a few days when you want to try it in your production or in your real world project.

But then it isn’t a big problem and you aren’t so surprised.

On the opposite. More, I am quite happy if my code gets reverted because TCR reverts only one line of code in my projects because I got so used to baby steps that I normally write one line of code before TCR can kick in and then it just deletes bad code that is just wrong. I don’t have to think if my code is currently green, or if I could ship it to a customer, or if it works, because at every second when I’m typing I’m sure that my code is actually working.

My brain is filled with a combination of, I don’t know, like those old cartoons. There’s a little angel on one shoulder and a little devil on the other. I’m not sure which is which, but it both sounds awesome and horrible at the same time. On one side, I’ve got this notion that a lot of programmers think of their code as too precious, and I often recommend to people the first time they solve an unusual problem to completely solve it. And now throw your code away and don’t even look at it and do it again. Because the developer, that developer that’s already solved the problem once is the perfect person to solve it again. It’s going to be like you start like writing, you do a rough draft and then you go through it again and you write it a second time. On the other hand, there’s not just the emotional side of I don’t want my code deleted, but there’s the context switch time of just going, just doing little tiny steps every time.

Doesn’t it slow you down? Are you developing software slower than you could otherwise?

I didn’t experience it in the past because TCR pushes you to the best practices you always have.

When you do TV, you have, for example, do baby steps or in the bigger scope, the TD strategies, for example, London style or Chicago style, where loan styles means that you begin at the very outer layer of the system and then you mock the underlying dependencies and then you replace these marks with implementations and mock these dependencies and then you implement these mocks and so on until you reach the bottom or the bottom up Chicago style approach where you begin with very low level tests and build up your test suit until you reach the outer layers of your system. And with TDD this is optional and you have to be very disciplined doing this.

With TCR, you don’t have much options.

You have to follow one of these strategies or one of the other strategies of TDD that you are able to split your work in baby steps and it is certainly possible. And when you do it, you aren’t any slower, you just go another way and a very safe way.

On the other hand, I don’t spend too much time on bug fixing anymore because in the past when I did the TV and I work late hours, I just dropped the practice a little bit and just wrote some production code and had no coverage. Or I wrote bad unit tests and stuff like this because when you do test first without tool that checks, if you really do it, you have to bring up the discipline doing it with TCR, on the other hand, you don’t have the option not to write a unit test before or just implement the production code because you always have the bet that the code that you just wrote gets reverted and therefore you just do the TD strategies that are good and that can make you very efficient. And after some time you don’t spend thinking too much about the strategies, but they become natural and you just do it. And the result is source code that is very well tested and developed with very tiny steps where you always refactor the system on the fly. I experienced that, especially the refactoring parts gets dropped with TDD, because with TDD you have this red state, green state, and maybe someday the yellow state where you do refactoring with TCR. Refactoring is very essential for the workflow.

Now, I know that you said that with C Plus Plus it was a little difficult. So what languages do you use where you do use TCR, and it’s a little easier.

With Java, we were able to split our project in such tiny modules that each module were available independently, and all the tests ran independently. So we had very good builds and test times there. And I just finished a project with Elixir, which worked quite fine.

I guess every interpreted language like Python or PHP should work very well. And let me think, I guess. Yes, someday I did a closure project with TCR as well.

You’re keeping track of coverage, correct?

Personally, I do, but it isn’t required for TCR.

But it happens naturally that you have a big code coverage, because when you write too much production code without a test, the NAICS test that fail could revert the whole code and you don’t write on the other side too much production code. For now, let me think. You normally don’t write two or three failing unit tests at once, because then it becomes nearly impossible to write code that isn’t reversed immediately.

All right, yeah, that would be tough. You could if you wanted to hook up coverage as a requirement as well. That wouldn’t be too terrible to hook that up into the test system to say if you drop coverage, revert your code also, sure.

I had another concept. It’s called coverage delete.

It is just an idea. I didn’t create a prototype yet, but it’s in my queue where a tool checks which lines of codes are covered in a test coverage tool and just deletes the ones that aren’t covered in a test coverage. So it’s a kind of a garbage collector for your source code, because you never have to worry about that code again.

Well, you definitely could mess up some else clauses and stuff like that.

As I said, I didn’t implement the prototype. It was just a conceptual idea. But sure, a unit or a test that just measures code coverage is fine.

It’s not unusual to have, like continuous integration merge request rules to say we run the test on them.

They have to all pass, but also the coverage has to stay at whatever level it was before.

Sure, we have the same, but we don’t have it in our unit test, so it wasn’t included in TCR.

Now, when you’re done with all this TCR thing to build up all your components, is this akin to how you’re writing your unit tests? So are there higher level tests that are written in a different fashion with TCR? Well, like your system tests.

Yes. And I didn’t do it consistently in the past project. I did.

I think a good example was acceptance test I wrote.

I tried on a web app, the dominant style approach. I’ve written an acceptance test and just faked all the behavior on the boundary of the system. And then I created everything with TCR and replaced both mocks with an implementation.

I’ve go on down to the level, down to a database, for example. So you can do systems and integration tests when they don’t take too long, because then it becomes unprecedentable to do it because you have to have a very short feedback time.

Right? I mean, it becomes impractical, too. I guess that’s what I understand is that a lot of the feedback, including all the system and full tests, might make the TCR loop too slow. If you’re running those all the time, however, you do have to at some point test the entire system.

Sure.

But just because it do TCR when you create new codes, you always can keep the old techniques for testing the whole system.

You still can run your systems and integration test in the CI pipeline, for example, but then your code doesn’t get reverted, for example. Sure. I used TCR in the act of really writing new code and have the slow stuff still in the CI pipeline.

Okay, that makes sense.

So this is something if you’re still teaching people about it, I’m assuming it’s something you still think is a good thing and you’re going to continue with sure.

These days, I think it could be a thing that I will do in five years. When I started, I was just curious, and then I thought, it can’t possibly work in a real project. And then I did some projects with it, and then I gave some talks and everybody else said, no, this can’t work. And so but then I collected all the arguments against TCR in a Medium article, and I keep track of all downsides of TCR I hear at talks and workshops.

I think these days not too much comes to the list after workshop that I didn’t already hear. And for me, every problem that is listed is a solvable problem. And for me it has potential that it is an alternative to test driven development. And these days I’m confident that it could survive the next five years.

Okay, you’ve got a bunch of articles on TCR on Medium now?

Yes.

I decided to do my notes more in the public because I always written down some notes. And last year in autumn, I decided that I write more blog posts. I just transfer my notes in blog posts. And this was roughly the time when the first TCR article of mine came out. And since then I practiced TCR in my projects and I write down my experiences on it.

I’ve got a handful of blog articles that I’ve found, but I’ll ask you to pass me some too so that we can link to articles and whatnot on the show. Notes.

The original article from Kentuck is still a good one, the one he published in the end of September 2018, but it really doesn’t go in the details as every article of Kent Back.

Therefore I wrote my own this TCR article that you mentioned in the beginning. I think we can link it in a show notes and then you get at least the basics. And after this I really suggest that you just try it because they get prototype of TCR. You can use grid to do TCR is quite simple, and I published variants on TCR because TCR is very hard. It reverts everything, including all the tests and stuff like this. And I’ve created some variants of TCR that are a little bit more gentle to you.

And there are scripts included, and I would say that the best way is just download the script or just copy paste the script. It’s three line or so and just try to implement function that is a pure status function because it’s the easiest to test. And then maybe after this try something with state, and after this maybe a web app or something like this.

Okay, that’s cool. I like the idea of some variance. I’m sure you’ve already come up with this, but don’t revert everything. I’d like to try to not revert the test part maybe. I’m pretty sure the test is what I want. I don’t want the test to get deleted, so just revert the source code.

You mentioned a big problem with TCR with the pure form, and I don’t use the original TCR in my real project because they aren’t very practical because of two reasons.

The first big reason are typos. If you have a typo error, your code gets committed because the test isn’t able to run.

This is very annoying. Therefore I’ve created TCR so the script stops when it can’t build your project. So if you have any syntax error or something like this, your code doesn’t get committed or reverted, it just stops. So at least use at least Btcr, because otherwise every type leads to reversion of your code. And normally I use a variant that is called the Relaxed.

It just reverts your source code.

This solves the second big problem Besides the vanishing test problem.

The vanishing test problem means that your test gets reverted along with your production code, which is quite annoying because the tests often take much more effort to write than the fake production code. You have to create a test fixture and everything else, and in Java you have to write all the formal stuff around your search. And it is annoying that the code gets reverted when you do it. When your test gets reverted. When doing TCR, there are different techniques to prevent it, and one is the Relax, which just don’t revert the test code.

But this isn’t pure TCR anymore, because one key idea of TCR is that it can bring you back from a red state of your source code. Back To A Green State.

When You Don’t Revert The Test And You Have A Red Test, it Doesn’t Bring You Back To A Green State Because The Test Doesn’t Get Deleted And It Is Still Red. So Your Code Base Is In A Red State.

So it Isn’t Quite The Idea Of GCR, but For Me It Is A Very Practical Trade Off Because Then I Have one Failing Unit Test And Can Make It Green. I Still Don’t Want To Write Two Or three Failing Unit Tests, even If I Could With This Technique, because Then It Would Be Nearly Impossible To Write A Fake Behavior because if you Remember, whenever One Test Is Clean, The Production Code Gets Reverted. So I Have To Make All The Tests That I read. If It’s More Than One, I Have To Make Them Green With One Single Shot and At Best with One Single Fake.

And When You Have Two Or three Failing Unit Tests, It Becomes Very Difficult. Therefore, the Relax.

This Variant Of TCR Is The One That I Normally Use In My Product When I Do Research Projects, even If It Isn’t no Pure TCR.

Okay. Do You Have That Relaxed Example In One Of These Articles?

Yes. I Published Actually An Article TCR Variants, Where I Have About Ten Or 15 Different Variants Where I Provide Some Soil Coat And Give Some Advantages And Disadvantages Of Each Variant.

Okay, cool. All Right. Well, I’ve Got Some Homework To Do. This Is An Interesting Thing, and I Just Love It When People Talk About Different Ways To Do Development And Testing, and I’m Going To Reserve Judgment Until I Try It Myself. So I Definitely Want To Try To Put Some Of These Tools Together. So For Me, I Think The Relaxed One Sounds Pretty Good To Start With Because I Don’t Really Care About Being Pure. I Want To Be Effective. If that Seems Like It’s Going To Work, Maybe I’ll Try To Start There And Try Others. So Cool. Well, thank You So Much For Your Time Today. Thomas, And I’ll Probably Check In With You Again After I’ve Tried It Once.

Great. Brian. Thank You For Talking With Me.

Thanks Again To PyCharm For Sponsoring The Show. Get An Extended Four Months To Play With Pycharm at testandcode.com. Pycharm. That Link Is Also In The Show Notes at testandcode.com 68 The Show Notes also Have Links To The Articles We Discussed In Our Conversation. A big thank You To Patreon Supporters and A Special Thank You To New Five Dollar Supporters, Johnny Cochrane, Chris Fraser, And Michael Harp. Your Support Really Helps Keep The Show Going. And thank You For Listening, writing The Word About The Show. That’s All For Now. Now Go Ahead And Test Something. And If You Do Try TCR, Let Me Know What You think.