Upgrade to Pro — share decks privately, control downloads, hide ads and more …

android-testing-bootcamp-1

 android-testing-bootcamp-1

836437265cbba12ee1b24bbb359a6c15?s=128

Yuya Kaido

March 23, 2016
Tweet

More Decks by Yuya Kaido

Other Decks in Programming

Transcript

  1. ςελϒϧͳઃܭΛ ໝ૝ͯ͠Έͨ Android Testing Bootcamp #1 yuyakaido

  2. ࣗݾ঺հ • ւ౻༏໻ʢ͔͍Ͳ͏Ώ͏΍ʣ • גࣜձࣾΤ΢ϨΧ • ςετॻ͚ॻ͚͓͡͞Μ • Android 

    yuyakaido yuyakaido
  3. גࣜձࣾΤ΢ϨΧ • ࣗࣾαʔϏεͷاըɾ։ൃɾӡӦ • ΦϯϥΠϯσʔςΟϯάαʔϏεɿ • Χοϓϧઐ༻ΞϓϦɿ • ࣾһ਺ɿ100໊ •

    IAC  ΤϯδχΞ 60 ඇΤϯδχΞ 40
  4. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  5. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  6. ಈػ • େن໛ΞϓϦͷϝϯςφϯε͕ਏ͍ • ςετΛॻ͖͍͚ͨͲɺઃܭ͕ͪΌΜͱͯ͠ ͳ͍ͱςετ͕ॻ͖ʹ͍͘ • ςετ͕ॻ͖΍͍͢ઃܭΛໝ૝ͯ͠Έͨ 

  7. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  8. શମํ਑ • ܧଓతΠϯςάϨʔγϣϯ • ςετͷ࣮ߦ଎౓Λॏࢹ • ग़དྷΔ͚ͩJUnit/RobolectircͰςετ͢Δ • JUnit/Robolectricͩͱςετ͕೉͍͠ͱ͜ Ζ͚ͩ͸EspressoͰςετ͢Δ

    
  9. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  10. શମઃܭ  Repository UseCase Presenter View Dao Client Database Server

    Presentation Domain Infrastructure
  11. Presentation • Ͳ͏දࣔ͢Δ͔Λهड़ • MVPϞυΩ • Presenter͸Pure Java (ContextҎ֎) •

    Presenter͸JUnit/RobolectricͰςετ • View͸EspressoͰςετ(Robolectric΋ซ༻) 
  12. Domain • ԿΛ࣮ݱ͢Δ͔Λهड़ • Pure Java (ContextҎ֎) • JUnit/RobolectricͰςετ 

  13. Infrastructure • Ͳ͏΍࣮ͬͯݱ͢Δ͔Λهड़ • DB • API • Pure Java

    (ContextҎ֎) • JUnit/RobolectricͰςετ 
  14. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  15. Dagger • https://github.com/google/dagger • ຊ൪ͱςετͰΠϯελϯεͷࠩ͠ସ͑  PresentationModule DomainModule AppComponent InfraModule

    BarModule FooModule BazModule
  16. RxJava • https://github.com/ReactiveX/RxJava • ֤૚ΛObservableͰ࿈݁ • ࣮ߦ࣌ʹεϨου͕ࣗ༝ʹઃఆग़དྷΔͨΊɺ ςετ͕ॻ͖΍͘͢ͳΔ 

  17. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  18. ςετίʔυ • Client • Presenter • ৄ͘͠͸ͪ͜Β • https://github.com/yuyakaido/android-genesis 

  19. Client • GithubͷAPIΛ࢖ͬͨαϯϓϧ • ొ৔ਓ෺ • GithubClient 㲗 GithubClientTest •

    GithubInfraModule 㲗 GithubInfraTestModule 
  20. GithubClient public class GithubClient {
 
 private GithubService githubService;
 


    @Inject
 public GithubClient(GithubService service) {
 this.githubService = service;
 }
 
 public Observable<List<GithubContributor>> getGithubContributors(String owner, String repo) {
 return CommonClient.retry(githubService.getGithubContributors(owner, repo));
 }
 
 public Observable<List<GithubContributor>> getGithubContributors() {
 return getGithubContributors("konifar", "droidkaigi2016");
 }
 
 public interface GithubService {
 @GET("/repos/{owner}/{repo}/contributors")
 Observable<List<GithubContributor>> getGithubContributors(
 @Path("owner") String owner, @Path("repo") String repo);
 }
 
 }  ΞϓϦ
  21. GithubClient public class GithubClient {
 
 private GithubService githubService;
 


    @Inject
 public GithubClient(GithubService service) {
 this.githubService = service;
 }
 
 public Observable<List<GithubContributor>> getGithubContributors(String owner, String repo) {
 return CommonClient.retry(githubService.getGithubContributors(owner, repo));
 }
 
 public Observable<List<GithubContributor>> getGithubContributors() {
 return getGithubContributors("konifar", "droidkaigi2016");
 }
 
 public interface GithubService {
 @GET("/repos/{owner}/{repo}/contributors")
 Observable<List<GithubContributor>> getGithubContributors(
 @Path("owner") String owner, @Path("repo") String repo);
 }
 
 }  ΞϓϦ
  22. GithubClient public class GithubClient {
 
 private GithubService githubService;
 


    @Inject
 public GithubClient(GithubService service) {
 this.githubService = service;
 }
 
 public Observable<List<GithubContributor>> getGithubContributors(String owner, String repo) {
 return CommonClient.retry(githubService.getGithubContributors(owner, repo));
 }
 
 public Observable<List<GithubContributor>> getGithubContributors() {
 return getGithubContributors("konifar", "droidkaigi2016");
 }
 
 public interface GithubService {
 @GET("/repos/{owner}/{repo}/contributors")
 Observable<List<GithubContributor>> getGithubContributors(
 @Path("owner") String owner, @Path("repo") String repo);
 }
 
 }  ΞϓϦ
  23. GithubClient public class GithubClient {
 
 private GithubService githubService;
 


    @Inject
 public GithubClient(GithubService service) {
 this.githubService = service;
 }
 
 public Observable<List<GithubContributor>> getGithubContributors(String owner, String repo) {
 return CommonClient.retry(githubService.getGithubContributors(owner, repo));
 }
 
 public Observable<List<GithubContributor>> getGithubContributors() {
 return getGithubContributors("konifar", "droidkaigi2016");
 }
 
 public interface GithubService {
 @GET("/repos/{owner}/{repo}/contributors")
 Observable<List<GithubContributor>> getGithubContributors(
 @Path("owner") String owner, @Path("repo") String repo);
 }
 
 }  ΞϓϦ
  24. GithubInfraModule @Module
 public class GithubInfraModule {
 
 @Provides
 @Singleton
 public

    GithubClient.GithubService provideGithubService() {
 return ApiClientGenerator.generate(
 GithubClient.GithubService.class,
 "https://api.github.com");
 }
 
 }  ςετ
  25. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  26. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  27. GithubInfraTestModule @Module
 public class GithubInfraTestModule {
 
 @Provides
 public GithubClient.GithubService

    provideGithubService(MockWebServer mockWebServer) {
 return ApiClientGenerator.generate(
 GithubClient.GithubService.class,
 mockWebServer.url("").toString());
 }
 
 }  ςετ
  28. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  29. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  30. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  31. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  32. GithubClientTest public class GithubClientTest extends InfraTest {
 
 @Test
 public

    void getGithubContributorsTest() throws Exception {
 File file = new File("src/test/assets/json/github_contributors.json");
 MockWebServer mockWebServer = new MockWebServer();
 mockWebServer.enqueue(ResponseUtil.createMockResponse(file));
 mockWebServer.start();
 
 GithubInfraTestModule githubInfraTestModule = new GithubInfraTestModule();
 GithubClient githubClient = new GithubClient(
 githubInfraTestModule.provideGithubService(mockWebServer));
 
 TestSubscriber<List<GithubContributor>> testSubscriber = new TestSubscriber<>();
 githubClient.getGithubContributors().subscribe(testSubscriber);
 
 testSubscriber.assertNoErrors();
 testSubscriber.assertCompleted();
 List<GithubContributor> githubContributors = testSubscriber.getOnNextEvents().get(0);
 assertThat(githubContributors.size(), is(1));
 }
 
 }  ςετ
  33. Clientͷςετ • square/okhttp/mockwebserver͕௒ศར • DaggerΛ࢖ͬͯϞοΫαʔόʔ΁ͷࠩ͠ସ͑ • JUnit/RobolectricͰߴ଎ʹςετՄೳ 

  34. Presenter • Clientͱಉ༷ʹGithubͷAPIΛ࢖ͬͨαϯϓϧ • ొ৔ਓ෺ • GithubPresenter 㲗 GithubPresenterTest 

  35. GithubPresenter public class GithubPresenter {
 
 @Inject
 Scheduler scheduler;
 


    private GithubView githubView;
 private GithubUseCase githubUseCase;
 
 public GithubPresenter(Context context, GithubView githubView, GithubUseCase githubUseCase) {
 Genesis.getGenesisComponent(context).inject(this);
 this.githubView = githubView;
 this.githubUseCase = githubUseCase;
 } ʢதུʣ
 
 }  ΞϓϦ
  36. GithubPresenter public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 public void onItemClick(GithubContributor githubContributor) {
 githubView.startWebViewActivity(githubContributor);
 } ʢதུʣ
 
 }  ΞϓϦ
  37. GithubPresenter public class GithubPresenter {
 
 public void refresh() {


    githubUseCase.getGithubContributors()
 .subscribeOn(scheduler)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Subscriber<List<GithubContributor>>() {
 @Override
 public void onCompleted() {
 }
 
 @Override
 public void onError(Throwable e) {
 }
 
 @Override
 public void onNext(List<GithubContributor> githubContributors) {
 githubView.setGithubContributors(githubContributors);
 githubView.hideProgressBar();
 }
 });
 } ʢதུʣ
 
 }  ΞϓϦ
  38. GithubPresenterTest public class GithubPresenterTest extends PresentationTest {
 
 private GithubView

    githubView;
 private GithubUseCase githubUseCase;
 private GithubPresenter githubPresenter;
 
 @Override
 public void setUp() {
 super.setUp();
 githubView = mock(GithubView.class);
 githubUseCase = mock(GithubUseCase.class);
 githubPresenter = new GithubPresenter(getContext(), githubView, githubUseCase);
 } ʢதུʣ
 
 }  ςετ
  39. GithubPresenterTest public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onCreateTest() {
 githubPresenter.onCreate();
 
 verify(githubView, times(1)).initViews();
 verify(githubView, times(1)).showProgressBar();
 verify(githubView, times(1)).refresh();
 }
 
 }  ςετ
  40. GithubPresenterTest public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onCreateTest() {
 githubPresenter.onCreate();
 
 verify(githubView, times(1)).initViews();
 verify(githubView, times(1)).showProgressBar();
 verify(githubView, times(1)).refresh();
 }
 
 }  ςετ
  41. GithubPresenterTest public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onCreateTest() {
 githubPresenter.onCreate();
 
 verify(githubView, times(1)).initViews();
 verify(githubView, times(1)).showProgressBar();
 verify(githubView, times(1)).refresh();
 }
 
 }  ςετ
  42. GithubPresenterTest public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onCreateTest() {
 githubPresenter.onCreate();
 
 verify(githubView, times(1)).initViews();
 verify(githubView, times(1)).showProgressBar();
 verify(githubView, times(1)).refresh();
 }
 
 }  ςετ
  43. GithubPresenterTest public class GithubPresenter {
 
 public void onCreate() {


    githubView.initViews();
 githubView.showProgressBar();
 githubView.refresh();
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onCreateTest() {
 githubPresenter.onCreate();
 
 verify(githubView, times(1)).initViews();
 verify(githubView, times(1)).showProgressBar();
 verify(githubView, times(1)).refresh();
 }
 
 }  ςετ
  44. GithubPresenterTest public class GithubPresenter {
 public void refresh() {
 githubUseCase.getGithubContributors()


    .subscribeOn(scheduler)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Action1<List<GithubContributor>>() {
 @Override
 public void call(List<GithubContributor> githubContributors) {
 githubView.setGithubContributors(githubContributors);
 githubView.hideProgressBar();
 }
 });
 }
 } public class GithubPresenterTest extends PresentationTest {
 @Test
 public void refreshTest() {
 Observable<List<GithubContributor>> observable = Observable.create(
 new Observable.OnSubscribe<List<GithubContributor>>() {
 @Override
 public void call(Subscriber<? super List<GithubContributor>> subscriber) {
 subscriber.onNext(new ArrayList<GithubContributor>());
 subscriber.onCompleted();
 }
 }
 );
 when(githubUseCase.getGithubContributors()).thenReturn(observable);
 
 githubPresenter.refresh();
 
 verify(githubView, times(1)).setGithubContributors(new ArrayList<GithubContributor>());
 verify(githubView, times(1)).hideProgressBar();
 }
 }  ςετ
  45. GithubPresenterTest public class GithubPresenter {
 public void refresh() {
 githubUseCase.getGithubContributors()


    .subscribeOn(scheduler)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Action1<List<GithubContributor>>() {
 @Override
 public void call(List<GithubContributor> githubContributors) {
 githubView.setGithubContributors(githubContributors);
 githubView.hideProgressBar();
 }
 });
 }
 } public class GithubPresenterTest extends PresentationTest {
 @Test
 public void refreshTest() {
 Observable<List<GithubContributor>> observable = Observable.create(
 new Observable.OnSubscribe<List<GithubContributor>>() {
 @Override
 public void call(Subscriber<? super List<GithubContributor>> subscriber) {
 subscriber.onNext(new ArrayList<GithubContributor>());
 subscriber.onCompleted();
 }
 }
 );
 when(githubUseCase.getGithubContributors()).thenReturn(observable);
 
 githubPresenter.refresh();
 
 verify(githubView, times(1)).setGithubContributors(new ArrayList<GithubContributor>());
 verify(githubView, times(1)).hideProgressBar();
 }
 }  ςετ
  46. GithubPresenterTest public class GithubPresenter {
 public void refresh() {
 githubUseCase.getGithubContributors()


    .subscribeOn(scheduler)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Action1<List<GithubContributor>>() {
 @Override
 public void call(List<GithubContributor> githubContributors) {
 githubView.setGithubContributors(githubContributors);
 githubView.hideProgressBar();
 }
 });
 }
 } public class GithubPresenterTest extends PresentationTest {
 @Test
 public void refreshTest() {
 Observable<List<GithubContributor>> observable = Observable.create(
 new Observable.OnSubscribe<List<GithubContributor>>() {
 @Override
 public void call(Subscriber<? super List<GithubContributor>> subscriber) {
 subscriber.onNext(new ArrayList<GithubContributor>());
 subscriber.onCompleted();
 }
 }
 );
 when(githubUseCase.getGithubContributors()).thenReturn(observable);
 
 githubPresenter.refresh();
 
 verify(githubView, times(1)).setGithubContributors(new ArrayList<GithubContributor>());
 verify(githubView, times(1)).hideProgressBar();
 }
 }  ςετ
  47. GithubPresenterTest public class GithubPresenter {
 public void refresh() {
 githubUseCase.getGithubContributors()


    .subscribeOn(scheduler)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Action1<List<GithubContributor>>() {
 @Override
 public void call(List<GithubContributor> githubContributors) {
 githubView.setGithubContributors(githubContributors);
 githubView.hideProgressBar();
 }
 });
 }
 } public class GithubPresenterTest extends PresentationTest {
 @Test
 public void refreshTest() {
 Observable<List<GithubContributor>> observable = Observable.create(
 new Observable.OnSubscribe<List<GithubContributor>>() {
 @Override
 public void call(Subscriber<? super List<GithubContributor>> subscriber) {
 subscriber.onNext(new ArrayList<GithubContributor>());
 subscriber.onCompleted();
 }
 }
 );
 when(githubUseCase.getGithubContributors()).thenReturn(observable);
 
 githubPresenter.refresh();
 
 verify(githubView, times(1)).setGithubContributors(new ArrayList<GithubContributor>());
 verify(githubView, times(1)).hideProgressBar();
 }
 }  ςετ
  48. GithubPresenterTest public class GithubPresenter { 
 public void onItemClick(GithubContributor githubContributor)

    {
 githubView.startWebViewActivity(githubContributor);
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onItemClickTest() {
 githubPresenter.onItemClick(null);
 
 verify(githubView, times(1)).startWebViewActivity(null);
 }
 
 }  ςετ
  49. GithubPresenterTest public class GithubPresenter { 
 public void onItemClick(GithubContributor githubContributor)

    {
 githubView.startWebViewActivity(githubContributor);
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onItemClickTest() {
 githubPresenter.onItemClick(null);
 
 verify(githubView, times(1)).startWebViewActivity(null);
 }
 
 }  ςετ
  50. GithubPresenterTest public class GithubPresenter { 
 public void onItemClick(GithubContributor githubContributor)

    {
 githubView.startWebViewActivity(githubContributor);
 }
 
 } public class GithubPresenterTest extends PresentationTest {
 
 @Test
 public void onItemClickTest() {
 githubPresenter.onItemClick(null);
 
 verify(githubView, times(1)).startWebViewActivity(null);
 }
 
 }  ςετ
  51. Presenterͷςετ • ந৅Խ͞ΕͨUseCaseͱView • ͦΕΒʹର͢ΔΠϯλϥΫγϣϯ͕ద੾ʹߦ ΘΕ͍ͯΔ͔Λςετ • JUnit/RobolectricͰߴ଎ʹςετՄೳ 

  52. ໨࣍ • ಈػ • શମํ਑ • શମઃܭ • DaggerͱRxJava •

    ςετίʔυ • ·ͱΊ 
  53. ·ͱΊ • PresentationɿͲ͏දࣔ͢Δ͔ • DomainɿԿΛ࣮ݱ͢Δ͔ • InfrastructureɿͲ͏΍࣮ͬͯݱ͢Δ͔ • DIΛ࢖ͬͯຊ൪ͱςετͰΠϯελϯεΛ੾Γସ͑Δ •

    RxJavaΛ࢖࣮ͬͯߦεϨουͷ੾Γସ͑ 
  54. ·ͱΊ • ϝϦοτ • ֤૚ͷ໾ׂͱґଘؔ܎Λ੔ཧͨ͜͠ͱͰςελϒϧͳઃܭʹ • Android΁ͷґଘΛ࠷খݶʹͨ͜͠ͱͰߴ଎ͳςετՄೳʹ • σϝϦοτ •

    Ϋϥε਺͕ଟ͍ • νʔϜ։ൃͷ৔߹͸͋Δఔ౓ͷυΩϡϝϯτ͕ඞਢ 
  55.  ΤϯδχΞ ઈࢍ࠾༻தʂ ฐࣾ$%0 ʢνʔϑɾυοάɾΦϑΟαʔʣ ͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ

  56. Thank you :) Credit: NASA Earth Observatory/NOAA NGDC

  57. ิ଍ࢿྉ 

  58. CommonClient public class CommonClient {
 
 private static final int

    RETRY_COUNT = 3;
 private static final int RETRY_DELAY = 3;
 
 public static <T> Observable<T> retry(Observable<T> observable) {
 return observable.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
 @Override
 public Observable<?> call(Observable<? extends Throwable> observable) {
 return observable.take(RETRY_COUNT).flatMap(new Func1<Throwable, Observable<?>>() {
 @Override
 public Observable<?> call(Throwable throwable) {
 return Observable.timer(RETRY_DELAY, TimeUnit.SECONDS);
 }
 });
 }
 });
 }
 
 } 
  59. ApiClientGenerator public class ApiClientGenerator {
 
 public static <T> T

    generate(Class<T> clazz, String baseUrl) {
 return new Retrofit.Builder()
 .client(HttpClient.getInstance())
 .baseUrl(baseUrl)
 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 .addConverterFactory(GsonConverterFactory.create())
 .build()
 .create(clazz);
 }
 
 } 
  60. HttpClient public class HttpClient {
 
 private static OkHttpClient instance;


    
 private HttpClient() {}
 
 public static synchronized OkHttpClient getInstance() {
 if (instance == null) {
 HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
 httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
 instance = new OkHttpClient.Builder()
 .addInterceptor(httpLoggingInterceptor)
 .addNetworkInterceptor(new StethoInterceptor())
 .build();
 }
 
 return instance;
 }
 
 } 
  61. GithubView public interface GithubView {
 
 void initViews();
 void refresh();


    void showProgressBar();
 void hideProgressBar();
 void setGithubContributors(List<GithubContributor> githubContributors);
 void startWebViewActivity(GithubContributor githubContributor);
 
 } 
  62. GithubUseCase public interface GithubUseCase {
 
 Observable<List<GithubContributor>> getGithubContributors();
 
 }