{"url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280","forks_url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/forks","commits_url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/commits","id":"541927e083dcaa78532a8f6fef9bd280","node_id":"MDQ6R2lzdDU0MTkyN2UwODNkY2FhNzg1MzJhOGY2ZmVmOWJkMjgw","git_pull_url":"https://gist.github.com/541927e083dcaa78532a8f6fef9bd280.git","git_push_url":"https://gist.github.com/541927e083dcaa78532a8f6fef9bd280.git","html_url":"https://gist.github.com/michaellihs/541927e083dcaa78532a8f6fef9bd280","files":{"outside-in-tdd.md":{"filename":"outside-in-tdd.md","type":"text/markdown","language":"Markdown","raw_url":"https://gist.githubusercontent.com/michaellihs/541927e083dcaa78532a8f6fef9bd280/raw/5ba2eb5be607fa9720244a718419c8667fffe50e/outside-in-tdd.md","size":3401,"truncated":false,"content":"Transcript from Outside-In TDD\n==============================\n\n* [part 1](https://youtu.be/XHnuMjah6ps)\n* [part 2](https://www.youtube.com/watch?v=gs0rqDdz3ko)\n* [part 3](https://www.youtube.com/watch?v=R9OAt9AOrzI)\n* [Bank Kata](https://github.com/sandromancuso/Bank-kata)\n\n\nPart 1\n------\n\n* write acceptance test first (name it `...Feature` in a package `feature`)\n  * identify side effects - what are we testing (e.g. text printed to console)\n  * identify the trigger of the side effect (e.g. print statement on account)\n* drive implementation from test\n* use `UnsupportedOperationException` for all methods... that are not yet implemented, to see where things are failing\n  * change template of creating a new method in the IDE to create a `throw` statement in the body of the method\n* acceptance testing means:\n  * run trigger for side effect\n  * assure expected side effect has happened\n* as acceptance test is failing for the right reason, it's time to \"park\" the acceptance test and go to the inner loop --> unit testing\n* *META* split IDE editor: test left, implementation right\n* Outside-In TDD is doing design while writing the tests\n* use `void` command methods (no return value)\n* do not store things in objects that you can calculate on the fly\n  * only if calculation takes too much time\n* *META* create a shortcut `test` in the IDE that generates a test method stub (template)\n* start your tests with `<CLAAS>Should`\n* do not use / implement methods just for the purpose of testing\n* when mocking a class / classes, use `@RunWith(MockitoJUnitRunner.class)`\n* in acceptance test use real repository, in unit test mock it\n  * in unit test, mock external world\n* with introducing a repository, a logic is pushed further down into the system (from `Account` into `TransactionRepository`)\n\n\nPart 2\n------\n\n* Question to ask when doing outside-in TDD: \n  * is the responsibility of class under test to do all of that \n  * or is it the responsibility of someone else\n* keep all the methods of a class on the same level of abstraction\n* every time a collaborator of the class under test in the acceptance test is created, a method body of this collaborator will throw a `UnsupportedOperationException`\n  * this way we will be guided on what needs to be implemented next...\n  * therefore the Acc tests runs the real class, not the mocks\n  * as part of the outside-in process, this  means that we start with the class under test and are then guided to the missing points of implementation in the collaborator classes\n* each collaborator then gets a unit test as the next step\n  * within the unit test, we can think of what the collaborator class should do\n  * collaborators of the class under test in the unit tests are mocked\n* how to mock things like a date\n  * e.g. the transaction is saved in the database with a given date, which normally will be created \"in time\"\n  * rule: you can't test what you can't controll (e.g. `System.date()`)\n  * you need to controll this randomness in your tests\n  * so you need the `System.date()` to come from something that you can control / mock, e.g. a `Clock` class\n* META* check Idea shortcut for \"recent runs\" --> select recent runs of unit tests\n* when you need to test some functionality that you can't control (e.g. a clock / date / time), put the call to this functionality into a `protected` method and override the class / this method in your test","encoding":"utf-8"}},"public":true,"created_at":"2019-03-22T22:24:55Z","updated_at":"2022-09-11T07:12:07Z","description":"Outside-In TDD","comments":0,"user":null,"comments_enabled":true,"comments_url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/comments","owner":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"forks":[{"url":"https://api.github.com/gists/df12ac3814e298c3c333e4673998dc10","user":{"login":"enixdark","id":4610828,"node_id":"MDQ6VXNlcjQ2MTA4Mjg=","avatar_url":"https://avatars.githubusercontent.com/u/4610828?v=4","gravatar_id":"","url":"https://api.github.com/users/enixdark","html_url":"https://github.com/enixdark","followers_url":"https://api.github.com/users/enixdark/followers","following_url":"https://api.github.com/users/enixdark/following{/other_user}","gists_url":"https://api.github.com/users/enixdark/gists{/gist_id}","starred_url":"https://api.github.com/users/enixdark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/enixdark/subscriptions","organizations_url":"https://api.github.com/users/enixdark/orgs","repos_url":"https://api.github.com/users/enixdark/repos","events_url":"https://api.github.com/users/enixdark/events{/privacy}","received_events_url":"https://api.github.com/users/enixdark/received_events","type":"User","user_view_type":"public","site_admin":false,"name":"Cqshinn","company":null,"blog":"","location":null,"email":null,"hireable":true,"bio":"Technical","twitter_username":"enix_dark","public_repos":1405,"public_gists":119,"followers":134,"following":59,"created_at":"2013-06-04T12:13:51Z","updated_at":"2026-01-31T02:04:40Z"},"id":"df12ac3814e298c3c333e4673998dc10","created_at":"2019-10-30T04:32:17Z","updated_at":"2019-10-30T04:32:17Z"},{"url":"https://api.github.com/gists/a68d4f2b92cc70a5219e4bfd4aac0907","user":{"login":"dpraimeyuu","id":6437191,"node_id":"MDQ6VXNlcjY0MzcxOTE=","avatar_url":"https://avatars.githubusercontent.com/u/6437191?v=4","gravatar_id":"","url":"https://api.github.com/users/dpraimeyuu","html_url":"https://github.com/dpraimeyuu","followers_url":"https://api.github.com/users/dpraimeyuu/followers","following_url":"https://api.github.com/users/dpraimeyuu/following{/other_user}","gists_url":"https://api.github.com/users/dpraimeyuu/gists{/gist_id}","starred_url":"https://api.github.com/users/dpraimeyuu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dpraimeyuu/subscriptions","organizations_url":"https://api.github.com/users/dpraimeyuu/orgs","repos_url":"https://api.github.com/users/dpraimeyuu/repos","events_url":"https://api.github.com/users/dpraimeyuu/events{/privacy}","received_events_url":"https://api.github.com/users/dpraimeyuu/received_events","type":"User","user_view_type":"public","site_admin":false,"name":"Damian Płaza","company":null,"blog":"https://talesfrom.dev","location":"Poland","email":null,"hireable":null,"bio":null,"twitter_username":"raimeyuu","public_repos":77,"public_gists":15,"followers":50,"following":118,"created_at":"2014-01-18T13:50:21Z","updated_at":"2026-03-25T17:35:36Z"},"id":"a68d4f2b92cc70a5219e4bfd4aac0907","created_at":"2022-09-11T07:12:07Z","updated_at":"2022-09-11T07:12:07Z"}],"history":[{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"cfe85ed1a47842816d2bf1cb467d7b2a548d6299","committed_at":"2019-03-26T21:39:29Z","change_status":{"total":3,"additions":2,"deletions":1},"url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/cfe85ed1a47842816d2bf1cb467d7b2a548d6299"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"968bc62e30ee5a03160c6e0ce663c1838729f4db","committed_at":"2019-03-24T21:13:28Z","change_status":{"total":16,"additions":15,"deletions":1},"url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/968bc62e30ee5a03160c6e0ce663c1838729f4db"},{"user":{"login":"michaellihs","id":575011,"node_id":"MDQ6VXNlcjU3NTAxMQ==","avatar_url":"https://avatars.githubusercontent.com/u/575011?v=4","gravatar_id":"","url":"https://api.github.com/users/michaellihs","html_url":"https://github.com/michaellihs","followers_url":"https://api.github.com/users/michaellihs/followers","following_url":"https://api.github.com/users/michaellihs/following{/other_user}","gists_url":"https://api.github.com/users/michaellihs/gists{/gist_id}","starred_url":"https://api.github.com/users/michaellihs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michaellihs/subscriptions","organizations_url":"https://api.github.com/users/michaellihs/orgs","repos_url":"https://api.github.com/users/michaellihs/repos","events_url":"https://api.github.com/users/michaellihs/events{/privacy}","received_events_url":"https://api.github.com/users/michaellihs/received_events","type":"User","user_view_type":"public","site_admin":false},"version":"d351b2b13966a6159e865cb162d420ac4bf6a799","committed_at":"2019-03-22T22:24:55Z","change_status":{"total":42,"additions":42,"deletions":0},"url":"https://api.github.com/gists/541927e083dcaa78532a8f6fef9bd280/d351b2b13966a6159e865cb162d420ac4bf6a799"}],"truncated":false}