43
Clean Architecture & TDD @fushiroyama

Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Clean Architecture & TDD@fushiroyama

Page 2: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

About Me

• Fumihiko Shiroyama

• Android App Developer

• Unit Test Enthusiast

• https://github.com/srym

Page 3: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Clean Architecture

• Presentation

• Domain

• Infrastructure

Page 4: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

TDD

• Test Driven Development

• Test First

• Minimum Implementation

• Refactoring

Page 5: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

TDD is great! because...

• Focus on I/O

• Less reworking

• Force Unit Testing

Page 6: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Example

• Infrastructure

• Remote Data Source

• GitHub Information

• Local Unit Test

Page 7: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Interface

public interface RemoteGitHubDataSource { Single<List<Repo>> listRepos(@NonNull String user);}

Page 8: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Blank Implementation

public class RestGitHubDataSource implements RemoteGitHubDataSource { @Override public Single<List<Repo>> listRepos(@NonNull String user) { return Single.error(new RuntimeException()); }}

Page 9: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Blank Implementation

public class RestGitHubDataSource implements RemoteGitHubDataSource { @Override public Single<List<Repo>> listRepos(@NonNull String user) { return Single.error(new RuntimeException()); }}

Page 10: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Create Test

• Mouse over class

• Alt + Enter

• Create Test

Page 11: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Create Test

Page 12: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Create Test

Page 13: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

By the way...

• Mouse over class

• Shift + Command + T

• Choose Test

Page 14: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Test First

public class RestGitHubDataSourceTest { private RestGitHubDataSource dataSource;

@Before public void setUp() throws Exception { dataSource = new RestGitHubDataSource(); }

@Test public void listRepos() throws Exception { // implement here! }}

Page 15: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Test First

@Testpublic void listRepos() throws Exception { List<Repo> repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values() .get(0); assertThat(repos).isNotNull();}

Page 16: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Test First

assertThat(repos).isNotNull().isNotEmpty();Repo repo = repos.get(0);assertThat(repo).isNotNull();assertThat(repo.getFullName()).isNotBlank();assertThat(repo.getId()).isGreaterThanOrEqualTo(0);assertThat(repo.getOwner()).isNotNull();

Page 17: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Test First

assertThat(repos).isNotNull().isNotEmpty();Repo repo = repos.get(0);assertThat(repo).isNotNull();assertThat(repo.getFullName()).isNotBlank();assertThat(repo.getId()).isGreaterThanOrEqualTo(0);assertThat(repo.getOwner()).isNotNull();

You can confirm the specs BEFORE you implement

Page 18: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Test Execution (failure)

• This of course fails.

Page 19: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Minimum Implementation

public class RestGitHubDataSource implements RemoteGitHubDataSource { private final GitHubService gitHubService;

@Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; }

@Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); }}

Page 20: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Minimum Implementation

public class RestGitHubDataSource implements RemoteGitHubDataSource { private final GitHubService gitHubService;

@Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; }

@Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); }}

Page 21: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Minimum Implementation

public class RestGitHubDataSource implements RemoteGitHubDataSource { private final GitHubService gitHubService;

@Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; }

@Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); }}

Page 22: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

But wait...

• This is Local Unit Test

• Mock data? Hmm.

Page 23: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

Page 24: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

• Provided by OkHttp

• Full HTTP Stack

• Can test REAL response

Page 25: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

private final MockWebServer mockWebServer = new MockWebServer();

Page 26: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { return new MockResponse().setResponseCode(404); }};mockWebServer.setDispatcher(dispatcher);mockWebServer.start();

Page 27: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

@Overridepublic MockResponse dispatch(RecordedRequest request) throws InterruptedException { if (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); }

if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); }

return new MockResponse().setResponseCode(404);}

Page 28: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

@Overridepublic MockResponse dispatch(RecordedRequest request) throws InterruptedException { if (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); }

if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); }

return new MockResponse().setResponseCode(404);}

Page 29: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

@Overridepublic MockResponse dispatch(RecordedRequest request) throws InterruptedException { if (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); }

if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); }

return new MockResponse().setResponseCode(404);}

Page 30: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

@Overridepublic MockResponse dispatch(RecordedRequest request) throws InterruptedException { if (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); }

if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); }

return new MockResponse().setResponseCode(404);}

Talk about this later

Page 31: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

Retrofit retrofit = new Retrofit.Builder() .baseUrl(mockWebServer.url("")) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();GitHubService gitHubService = retrofit.create(GitHubService.class);

Page 32: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

MockWebServer

Retrofit retrofit = new Retrofit.Builder() .baseUrl(mockWebServer.url("")) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();GitHubService gitHubService = retrofit.create(GitHubService.class);

Page 33: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Prepare Data

• Curl

• Postman

curl https://api.github.com/users/srym/repos > users_repos.json

Page 34: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Prepare Data

• Put it test/resources

Page 35: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Read JSON from file

private String readJsonFromResources(@NonNull String fileName) { InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder stringBuilder = new StringBuilder(); try { String buffer; while ((buffer = bufferedReader.readLine()) != null) { stringBuilder.append(buffer); } } catch (IOException e) { fail(e.getMessage(), e); } return stringBuilder.toString();}

Page 36: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Fix Test

@Before public void setUp() throws Exception { // abbr. dataSource = new RestGitHubDataSource(gitHubService); }

@Test public void listRepos() throws Exception { List<Repo> repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values() .get(0); assertThat(repos).isNotNull(); // abbr. }

Page 37: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Passed!

Page 38: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Refactoring

• TDD is NOT perfect

• Repeat Write & Test

Page 39: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Cons

• Useless when API changes

• Takes longer time

Page 40: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Pros

• Quality

• Relief

• Takes shorter time in total

Page 41: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

TDD rocks!

Page 42: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Thank You

Page 43: Clean Architecture & TDD · 2017. 9. 20. · • Android App Developer • Unit Test Enthusiast ... • Minimum Implementation • Refactoring. TDD is great! because... • Focus

Links

• https://github.com/srym/Architecture

• https://github.com/square/okhttp/tree/master/mockwebserver

• http://www.irasutoya.com/