dospro
dospro

Reputation: 490

How to do TDD for real time applications

I've been studying the discipline of Test Driven Development and for me it has worked well for implementing algorithms and input-output systems.

So, as far as I understand, the "essence" of TDD is to actually write tests for each requirement of the application. Normally this requirement defines a behavior with inputs and outputs.

So, now. Going to real time applications. Let´s say your application runs an infinite loop. A common example is a graphics application or an audio application where each iteration of the loop means output to the screen/speakers.

Having a system like that, let´s say the requirement is something like: "When pressing Enter button, the screen should show a circle with the text Hello World inside the circle"

So how would you test drive this kind of requirement.

Another example, just to illustrate my question better. Let´s say I´m emulating a CPU. In each iteration, I fetch an opcode from the file, translate it and execute it. Basically there is no actual output. What happens is there is input which changes some state related to the emulation of the CPU. So no public interface for the CPU internals.

My requirement would say something like "Implement the mov operation on the cpu emulator" Which may be part of the bigger requirement "Implement opcodes emulation"

So. What would be a good approach for tackling this behaviors/requirements using TDD?

Upvotes: 0

Views: 193

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57279

What would be a good approach for tackling this behaviors/requirements using TDD?

What I normally see happen is that the design partitions into two pieces

  • A piece that is complicated, but really "easy" to test
  • A piece that is hard to test, but is really "simple"

Basically, you are arranging that the "risk" lies predominantly in the code that is easy to test.

One of the properties of code that is really simple: it also tends to be very stable. The combination of low risk, stable, and difficult to test means that investing in test automation here is less attractive.

Basically there is no actual output.

The write a no-op; there's no advantage to doing any work that doesn't have an observable side effect of some sort.

It's a common pattern that we look at an intermediate stage of the output. For example, if we are supposed to produce a tone from the speakers, what we might do in code is create a seam between the work of choosing the tone, and the actual mechanism of delivering the representation of the tone to the speaker. At that seam, we also capture information so that we can check it.

So no public interface for the CPU internals.

Having a test interface is normally a satisfactory outcome. Often, it will turn out that you want to publish the test interface, for use in satisfying monitoring or observability requirements.

The public interface is way too broad to test that single behavior.

Yes, that's common. The usual response is to refactor your broad testable module into several, perhaps even many, narrow testable modules. Review Parnas 1971.

It may help also to think about the distinction between public methods (accessible outside a module) and published methods (accessible by code that you don't control).

Upvotes: 1

Related Questions