Skip to main content
added 3 characters in body
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84
Correct spelling errors
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84

I'm implementigimplementing a simple command line game

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the [test pyramid][1]test pyramid than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use [test doubles][2];test doubles; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

[JB Rainsberger wrote][3]JB Rainsberger wrote:

Gary Bernhardt's [Boundaries][4]Boundaries talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framwork"Framework" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

On the other hand, as soon as you introduce something like "we also need to be able to save and load games from the file system", I need to zoom out a few layers and work my way back inwards more slowly, with more tests to reach my confidence threshold. [1]: https://martinfowler.com/articles/practical-test-pyramid.html [2]: https://martinfowler.com/bliki/TestDouble.html [3]: https://blog.thecodewhisperer.com/permalink/beyond-mock-objects [4]: https://www.destroyallsoftware.com/talks/boundaries

I'm implementig a simple command line game

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the [test pyramid][1] than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use [test doubles][2]; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

[JB Rainsberger wrote][3]:

Gary Bernhardt's [Boundaries][4] talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framwork" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

On the other hand, as soon as you introduce something like "we also need to be able to save and load games from the file system", I need to zoom out a few layers and work my way back inwards more slowly, with more tests to reach my confidence threshold. [1]: https://martinfowler.com/articles/practical-test-pyramid.html [2]: https://martinfowler.com/bliki/TestDouble.html [3]: https://blog.thecodewhisperer.com/permalink/beyond-mock-objects [4]: https://www.destroyallsoftware.com/talks/boundaries

I'm implementing a simple command line game

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the test pyramid than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use test doubles; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

JB Rainsberger wrote:

Gary Bernhardt's Boundaries talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framework" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

On the other hand, as soon as you introduce something like "we also need to be able to save and load games from the file system", I need to zoom out a few layers and work my way back inwards more slowly, with more tests to reach my confidence threshold.

added 611 characters in body
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the test pyramid[test pyramid][1] than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use test doubles;[test doubles][2]; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

JB Rainsberger wrote [JB Rainsberger wrote][3]:

Gary Bernhardt's Boundaries[Boundaries][4] talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framwork" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

What I have found, in practice, is that as you become familiar with the basic isolation patterns, you tend to start "closer" to the interesting bits. So, for instance, if I'm writing an interactive CLI game, or a pipes-and-filters component, then I will just jump right past all of the plumbing tests and write the API signature straight from my head.

On the other hand, as soon as you introduce something like "we also need to be able to save and load games from the file system", I need to zoom out a few layers and work my way back inwards more slowly, with more tests to reach my confidence threshold. [1]: https://martinfowler.com/articles/practical-test-pyramid.html [2]: https://martinfowler.com/bliki/TestDouble.html [3]: https://blog.thecodewhisperer.com/permalink/beyond-mock-objects [4]: https://www.destroyallsoftware.com/talks/boundaries

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the test pyramid than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use test doubles; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

JB Rainsberger wrote:

Gary Bernhardt's Boundaries talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framwork" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

Your program is going to have a natural break between two parts - I/O and logic. Testing I/O is harder - it lives higher up the [test pyramid][1] than the logic tests. This is in part because the IO system tends to be shared; you can't as easily run two tests concurrently without them interfering with each other.

Moving down the pyramid, we're going to find some tests that use [test doubles][2]; in this case, a "stub" or a "fake" for STDIN and a "mock" or "spy" for STDOUT. So imagining an implementation of Game.main, it might look like:

[JB Rainsberger wrote][3]:

Gary Bernhardt's [Boundaries][4] talk is a great introduction to this concept.

No, I'm not suggesting that; although I will admit that it works. What I'm actually suggesting is slightly different -- that if you have the right arrangement of tests, you can iterate on your internal design until you have a "CLI Framwork" component and a core game logic component. The framework will be something that you can re-use for your next CLI app; the game logic will be something you can re-use when you decide your game should be accessible via a web api.

What I have found, in practice, is that as you become familiar with the basic isolation patterns, you tend to start "closer" to the interesting bits. So, for instance, if I'm writing an interactive CLI game, or a pipes-and-filters component, then I will just jump right past all of the plumbing tests and write the API signature straight from my head.

On the other hand, as soon as you introduce something like "we also need to be able to save and load games from the file system", I need to zoom out a few layers and work my way back inwards more slowly, with more tests to reach my confidence threshold. [1]: https://martinfowler.com/articles/practical-test-pyramid.html [2]: https://martinfowler.com/bliki/TestDouble.html [3]: https://blog.thecodewhisperer.com/permalink/beyond-mock-objects [4]: https://www.destroyallsoftware.com/talks/boundaries

added 1128 characters in body
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84
Loading
added 79 characters in body
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84
Loading
Source Link
VoiceOfUnreason
  • 34.7k
  • 2
  • 45
  • 84
Loading