diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 319aa8598547704a36ac7457755aea2d338d98ad..8dd2a570ae43ac761544a2972c94fe48b0af7e5a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,9 +77,11 @@ deploy: review-app: stage: deploy image: docker.io/dokku/ci-docker-image:0.9.3 + # Allow the job to fail when deploying rebased branch rules: - if: $CI_MERGE_REQUEST_ID when: on_success + allow_failure: true - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: never variables: diff --git a/docs/workshops/day_3_bdd.md b/docs/workshops/day_3_bdd.md index 665ff9f30b5897a2a00c7873479f142131adda7b..1fd88e4e6f5e51f7610e722c1f7389321ad7a92b 100644 --- a/docs/workshops/day_3_bdd.md +++ b/docs/workshops/day_3_bdd.md @@ -9,11 +9,11 @@ ## Functional Tests & BDD Anda telah diperkenalkan dengan contoh kode test dari tingkat _unit test_ hingga _functional test_ di hari pertama workshop. -_Unit test_ menguji komponen software terkecil ("unit", seperti fungsi, _class_, ataupun modul) secara independen dan, idealnya, terisolasi dari komponen lainnya. +_Unit test_ menguji komponen software terkecil ("unit", seperti fungsi dan _method_) secara independen dan, idealnya, terisolasi dari komponen lainnya. Sedangkan _functional test_ menguji software secara utuh dengan menyimulasikan interaksi pengguna ketika menggunakan software. Hari ini kita akan melihat bagaimana _functional test_ dapat dikembangkan lebih lanjut untuk mendukung proses pengembangan software dengan gaya Behavior-Driven Development (BDD). -Sebagai contoh, berikut ini adalah potongak kode sebuah _test case_ dari _functional test_ Sitodo PMPL yang menyimulasikan aksi menambahkan todo item baru: +Sebagai contoh, berikut ini adalah potongak kode sebuah _test case_ dari _functional test suite_ Sitodo PMPL yang menyimulasikan aksi menambahkan todo item baru: ```java @Test @@ -50,10 +50,10 @@ Ketiga peran tersebut berkolaborasi dalam proses pengembangan dengan menyusun _r ## Persiapan Workshop -Untuk mengikuti rangkaian kegiatan workshop hari ini, harap persiapkan _tools_ berikut di komputer anda: +Untuk mengikuti rangkaian kegiatan workshop hari ini, harap persiapkan _tools_ berikut di komputer: - Git -- IntelliJ Community Edition +- IntelliJ IDEA Community Edition - Pasang _plugin_ Cucumber - Java JDK 17 (`java` dan `javac`) - Apache Maven (`mvn`) @@ -61,11 +61,12 @@ Untuk mengikuti rangkaian kegiatan workshop hari ini, harap persiapkan _tools_ b - Google Chrome - Node.js (opsional jika ingin menjalankan _frontend_ secara manual) -Buat salinan _branch_ `development` dari repositori Git kode templat workshop hari ini: +Buka proyek [Spring Petclinic BDD di GitLab CSUI][Spring Petclinic BDD @ GitLab CSUI] dan +buat salinan proyek ("_fork_") ke dalam akun GitLab CSUI anda. +Kemudian buat salinan kode templat dari _fork_ ke komputer anda menggunakan perintah `git`: ```shell -# TODO: Siapkan _branch_ yang berisi templat kosong. Saat ini branch development masih mengandung contoh solusi. -git clone -b development https://gitlab.cs.ui.ac.id/pmpl/workshops/spring-petclinic-bdd.git +git clone https://gitlab.cs.ui.ac.id/[akun GitLab CSUI anda]/spring-petclinic-bdd.git ``` Telah tersedia juga berkas [`docker-compose.yml`][2] berikut untuk menjalankan aplikasi Spring Boot + Angular JS bernama Spring Petclinic yang akan dijadikan bahan latihan hari ini: @@ -74,7 +75,7 @@ Telah tersedia juga berkas [`docker-compose.yml`][2] berikut untuk menjalankan a --- services: api: - image: docker.io/addianto/spring-petclinic-rest:latest + image: docker.io/springcommunity/spring-petclinic-rest:3.0.2 ports: - "127.0.0.1:9966:9966" app: @@ -92,15 +93,15 @@ Apabila sudah menyalin repositori Git dan telah menyiapkan _tools_ yang dibutuhk silakan coba jalankan terlebih dahulu aplikasi contoh: ```shell -docker-compose up --detach -# Perintah alternatif. Tersedia pada instalasi Docker yang memasang plugin Compose. docker compose up --detach +# Alternatif lain jika menggunakan plugin Docker Compose melalui program docker-compose +docker-compose up --detach ``` Kemudian buka laman depan aplikasi menggunakan _web browser_ seperti Google Chrome di alamat `http://127.0.0.1`. Tampilan aplikasi akan terlihat serupa dengan _screenshot_ berikut: -> TODO: Tambah _screenshot_ + ## Templat Kode Spring Petclinic BDD @@ -143,15 +144,20 @@ Sebuah fitur dapat memiliki satu atau lebih skenario test. Pada contoh di atas, saat ini hanya ada sebuah skenario test untuk menguji fitur menambahkan bidang spesialis dokter hewan. Skenario test berisi tiga buah komponen penting di dalam membuat instruksi pengujian dengan gaya BDD: `Given`, `When`, dan `Then`. `Given` merepresentasikan kondisi awal skenario test sebelum menjalankan aksi aktor. -`When` merepresentasikan aksi aktor dalam sistem. +`When` merepresentasikan aksi aktor dalam SUT. `Then` merepresentasikan kondisi akhir skenario test setelah menjalankan aksi aktor. +Berikut ini adalah daftar referensi terkait sintaks Gherkin yang direkomendasikan: + +- [Gherkin Syntax - Cucumber Documentation](https://cucumber.io/docs/gherkin/) + ### Latihan Singkat: Menulis Deskripsi Fitur & Skenario Test Baru -> TODO: Tambah pengantar +Mari coba membuat sebuah deskripsi fitur beserta sebuah skenario test baru. +Silakan ikuti _tasks_ berikut: 1. [ ] Buat berkas deskripsi fitur baru bernama `manage_pet_types.feature` di `src/test/resources/features/veterinarian`. -2. [ ] Tulis nama fitur baru "Manage pet types" beserta deskripsinya. +2. [ ] Tulis nama fitur baru "Manage pet types" beserta deskripsi singkatnya. 3. [ ] Susun sebuah skenario test baru bernama "Add new pet type" yang menguji operator sistem dapat menambahkan sebuah jenis binatang peliharaan baru ke dalam sistem. Tulis skenarionya mengikuti kerangka `Given`, `When`, dan `Then`. @@ -167,29 +173,49 @@ Feature: Manage pet types Then she should see the pet type "turtle" on the list of pet types ``` +Apabila telah selesai, simpan hasil pekerjaan. +Buat _commit_ Git dan _push_ ke "_fork_" di GitLab CSUI. + ## Menjalankan Test Suite BDD -Jalankan skenario test menggunakan Run Configuration yang otomatis terdeteksi oleh IntelliJ. -Alternatif lain, jalankan skenario test menggunakan perintah Maven berikut: +_Test suite_ BDD dapat dijalankan dengan dua cara +yaitu menggunakan IDE (IntelliJ IDEA) atau menggunakan Maven di _shell_. +Jika anda ingin menjalankan _test suite_ BDD menggunakan IDE, +maka buka berkas _class_ Java yang merepresentasikan _test suite_ BDD, +yaitu _class_ [`CucumberTestSuite`][CucumberTestSuite] di IDE. +Kemudian jalankan _class_ tersebut dengan menekan tombol yang muncul di sisi kiri editor pada IDE +dan pilih _Run 'CucumberTestSuite'_ seperti yang tergambarkan di _screenshot_ berikut: + + + +Jika nyaman menggunakan _shell_ atau ingin menjalankan _test suite_ BDD di lingkungan _Continuous Integration_ (CI), +panggil perintah Maven berikut di _shell_: ```shell mvn verify ``` _Test suite_ BDD akan dijalankan oleh _test runner_ secara _headless_ terhadap aplikasi yang berjalan secara lokal. -Begitu _test suite_ BDD selesai dijalankan, laporan hasil test dapat ditemukan sebagai dokumen HTML di folder `target/site/serenity`. -Silakan buka berkas `index.html` yang terdapat di folder laporan hasil test. +Begitu _test suite_ BDD selesai dijalankan, laporan hasil test dapat ditemukan di folder `target/site/serenity`. +Apabila menggunakan Maven, perintah `mvn verify` juga akan menghasilkan laporan komplit hasil test sebagai dokumen HTML. Contoh tampilan laporannya dapat dilihat pada _screenshot_ berikut: -> TODO: Tambah _screenshot_ + -Dapat dilihat bahwa satu skenario test berhasil dijalankan, namun skenario test baru yang anda buat sebelumnya masih gagal. -Hal ini disebabkan karena skenario test yang anda buat belum disambungkan ke kode test. +Jika mengacu pada contoh laporan di atas, dapat dilihat contoh _test suite_ BDD mengandung tiga buah _test case_. +Dari tiga _test case_ tersebut, dua _test case_ berhasil dan satu _test case_ gagal. Deskripsi fitur memang bermanfaat bagi peran non-teknis agar dapat ikut berkontribusi di dalam proses pengembangan. -Namun bukan berarti deskripsi fitur dan skenario test secara ajaib bisa otomatis menguji coba sistem sesuai keinginan. +Namun bukan berarti deskripsi fitur dan skenario test secara ajaib bisa otomatis menguji coba SUT sesuai keinginan. Peran teknis seperti programmer dan _test engineer_ penting untuk dapat menyambungkan deskripsi fitur ke kode test. +> Catatan: Salah satu masalah yang umum terjadi ketika melakukan uji coba fungsionalitas melalui simulasi interaksi +> pada _user interface_ adalah hasil test yang tidak stabil. Ada kemungkinan skenario uji coba yang dijalankan oleh +> kode test tidak berhasil berinteraksi dengan elemen _user interface_ yang diinginkan. +> Pada aplikasi Web, isu elemen _user interface_ yang gagal ditemukan atau tidak bisa diujicobakan oleh kode test +> seringkali terjadi karena DOM Tree dari tampilan HTML belum sinkron. Hal ini sangat mungkin terjadi pada aplikasi +> Web dengan _user interface_ yang dibuat atau diubah oleh kode JavaScript. + ## Membuat Step Definition & Glue Code Mari lihat kembali contoh skenario test "Add new specialty": @@ -220,10 +246,10 @@ public void lookingAtSpecialtiesPage(Actor actor) { ``` _Step definition_ diimplementasikan sebagai fungsi dengan informasi tambahan yang akan memetakan fungsi tersebut dengan kalimat terkait. -Pada contoh di atas, fungsi diberikan anotasi `@Given` dengan parameter berisi teks _pattern_ yang akan dicocokkan dengan sebuah kalimat di skenario test. +Pada contoh di atas, fungsi diberikan anotasi `@Given` dengan parameter berisi teks _regular expression_ (_regex_) yang akan dicocokkan dengan kalimat di skenario test. Apabila kalimat pada skenario test mengandung elemen yang dapat berubah-ubah seperti aktor/pengguna fitur atau input, -maka teks _pattern_ dapat mengandung _placeholder_ yang akan menjadi parameter bagi fungsi _step definition_. +maka teks _regex_ dapat mengandung _placeholder_ yang akan menjadi parameter bagi fungsi _step definition_. Pada contoh di atas, `actor` merupakan tipe parameter khusus yang disediakan templat kode untuk memetakan aktor di skenario test dengan objek `Actor` yang akan dikendalikan oleh implementasi fungsi _step definition_. Inti utama dari fungsi _step definition_ adalah objek `Actor`, yaitu representasi dari aktor/pengguna fitur. @@ -279,7 +305,7 @@ public void shouldSeeTheSpecialty(Actor actor, String name) { ``` Pada contoh kode di atas, objek `Actor` sama-sama menggunakan fungsi `attemptsTo` seperti pada fungsi _step definition_ untuk kalimat `When`. -Hanya saja, parameter fungsi tersebut sebaikan diisi dengan objek `PerformablePredicate` yang dapat dibuatkan oleh objek `Ensure`. +Hanya saja, parameter fungsi tersebut sebaiknya diisi dengan objek `PerformablePredicate` yang dapat dibuatkan oleh objek `Ensure`. Objek `Ensure` menyediakan fungsi untuk merepresentasikan aksi verifikasi yang dilakukan oleh aktor terhadap kondisi akhir SUR. Aksi verifikasi yang dilakukan oleh aktor adalah sebagai berikut: @@ -287,7 +313,7 @@ Aksi verifikasi yang dilakukan oleh aktor adalah sebagai berikut: 2. Kemudian cek apakah nama bidang spesialis yang baru dimasukkan di antara seluruh input field yang ditemukan. Jika aksi verifikasi berhasil dilakukan, maka _test framework_ akan melaporkan skenario test tersebut berhasil/"pass". -Sebaliknya, jika ternyata verifikasi gagal dilakukan, maka _test framework_ akan melaporka skenario test tersebut gagal/"fail". +Sebaliknya, jika ternyata verifikasi gagal dilakukan, maka _test framework_ akan melaporkan skenario test tersebut gagal/"fail". Sebagai ringkasan, resep yang umum dipakai dalam membuat _step definition_ adalah sebagai berikut: @@ -309,24 +335,106 @@ ada baiknya kita mempelajari secara singkat bagaimana kita dapat merepresentasik ## XPath Serenity sebagai _test framework_ sudah menyediakan _library_ yang mempermudah pencarian elemen _user interface_ yang umum terlibat dalam interaksi aktor dengan SUT. -Sebagai contoh, kita dapat mendapatkan referensi terhadap elemen tombol dengan teks "Add" dengan memanggil `Button.withText("Add)`. -Namun akan ada kasus dimana kita elemen _user interface_ yang diinginkan berada di dalam struktur halaman yang cukup kompleks +Sebagai contoh, kita dapat mendapatkan referensi terhadap elemen tombol dengan teks "Add" dengan memanggil `Button.withText("Add")`, +dimana fungsi tersebut akan mencari elemen HTML `<button>` yang mengandung nilai teks "Add" di dalam struktur DOM Tree halaman HTML yang sedang dibuka. +Namun akan ada kasus dimana elemen _user interface_ yang diinginkan berada di dalam struktur halaman HTML yang cukup kompleks dan belum ada _library_ yang dapat membantu kita menemukan elemen tersebut. -<!-- TODO: Elaborasi dengan menjelaskan class-class yang tersedia di dalam _package_ `net.serenitybdd.screenplay.ui` --> +Sebagai contoh, mari lihat kode HTML untuk elemen tabel data pada halaman web fitur "Manage specialties": + +```html +<table _ngcontent-ng-c554405439="" id="specialties" class="table table-striped"> + <thead _ngcontent-ng-c554405439=""> + <tr _ngcontent-ng-c554405439=""> + <th _ngcontent-ng-c554405439="">Name</th> + <th _ngcontent-ng-c554405439=""></th> + <th _ngcontent-ng-c554405439=""></th> + </tr> + </thead> + <tbody _ngcontent-ng-c554405439=""> + <tr _ngcontent-ng-c554405439=""> + <td _ngcontent-ng-c554405439=""> + <input _ngcontent-ng-c554405439="" type="text" name="spec_name" class="form-control ng-untouched ng-pristine ng-valid" ng-reflect-name="spec_name" id="0" readonly="" ng-reflect-model="radiology"> + </td> + <td _ngcontent-ng-c554405439=""> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Edit</button> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Delete</button> + </td> + </tr> + <tr _ngcontent-ng-c554405439=""> + <td _ngcontent-ng-c554405439=""> + <input _ngcontent-ng-c554405439="" type="text" name="spec_name" class="form-control ng-untouched ng-pristine ng-valid" ng-reflect-name="spec_name" id="1" readonly="" ng-reflect-model="surgery"> + </td> + <td _ngcontent-ng-c554405439=""> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Edit</button> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Delete</button> + </td> + </tr> + <tr _ngcontent-ng-c554405439=""> + <td _ngcontent-ng-c554405439=""> + <input _ngcontent-ng-c554405439="" type="text" name="spec_name" class="form-control ng-untouched ng-pristine ng-valid" ng-reflect-name="spec_name" id="2" readonly="" ng-reflect-model="dentistry"> + </td> + <td _ngcontent-ng-c554405439=""> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Edit</button> + <button _ngcontent-ng-c554405439="" class="btn btn-default">Delete</button> + </td></tr><!--bindings={ + "ng-reflect-ng-for-of": "[object Object],[object Object" +}--></tbody> +</table> +``` + +Misalkan kita ingin menyimulasikan aksi pengguna dimana pengguna menekan tombol "Edit" pada item pertama di dalam tabel. +Dapat dilihat pada potongan HTML di atas bahwa ada tiga elemen `<button>` yang mengandung teks "Edit". +Bagaimana kita dapat mendapatkan referensi terhadap tombol "Edit" yang diinginkan? + +Salah satu algoritma yang dapat diikuti: + +1. Dapatkan referensi ke elemen HTML tabel yang diinginkan dan simpan referensinya ke dalam variabel `table`. +2. Melalui referensi `table`, dapatkan referensi ke badan utama tabel dan simpan referensinya ke dalam variable `tbody`. +3. Melalui referensi `tbody`, dapatkan referensi ke baris pertama tabel data dan simpan referensinya ke dalam variable `row`. +4. Melalui referensi `row`, dapatkan referensi ke kolom yang mengandung tombol dengan teks "Edit" dan simpan referensinya ke dalam variabel `column`. +5. Akhirnya, melalui referensi `column`, dapatkan referensi ke tombol di dalam kolom tersebut dan lakukan aksi klik pada tombol tersebut. + +Algoritma di atas dapat diimplementasikan menjadi serangkaian _statement_ pemanggilan fungsi-fungsi dari _library_ Serenity. +Namun ada alternatif lain yang lebih ringkas, yaitu menggunakan bahasa XPath. +XPath adalah bahasa yang digunakan untuk menulis ekspresi yang berisi sebuah pencarian pada dokumen XML atau HTML. +Instruksi pencarian elemen secara imperatif yang digambarkan pada contoh algoritma di atas dapat diringkas menjadi ekpresi singkat. + +Untuk dapat menuliskan XPath, kita perlu memahami bahasanya terlebih dahulu. +Terdapat beberapa referensi yang disebutkan di akhir bagian dokumen ini untuk mempelajari lebih lanjut. +Namun untuk keperluan workshop singkat ini, kita dapat menggunakan _shortcut_ yang disediakan _web browser_ untuk mengetahui ekspresi XPath sebuah elemen pada dokumen HTML. + +Buka halaman fitur "Manage specialties" dan buka Developer Tools di _web browser_. +Pilih "Inspect Element" lalu klik tombol "Edit" agar _web browser_ menampilkan kode HTML untuk tombol tersebut. +Kemudian klik kanan kode HTML tombol tersebut, lalu piih Copy > XPath seperti yang digambarkan pada _screenshot_ berikut: -Mari lihat potongan kode berikut yang diambil dari fungsi _step definition_ untuk mengubah nama bidang spesialis pertama pada daftar: + + +Coba salin ("_paste_") ekspresi XPath ke dalam _text editor_ untuk melihatnya. +Hasilnya dapat dilihat pada teks berikut: + +```xpath +/html/body/app-root/div[2]/app-specialty-list/div/div/table/tbody/tr[1]/td[2]/button[1] +``` + +Ekspresi XPath di atas dapat diringkas menjadi: + +```xpath +//table[@id='specialties']/tbody/tr[1]/td[2]/button[1] +``` + +Sebagai contoh penerapan XPath, lihat potongan kode berikut yang diambil dari fungsi _step definition_ untuk mengubah nama bidang spesialis pertama pada daftar: ```java Click.on(Button.located(By.xpath("//table[@id='specialties']/tbody/tr[1]/td[2]/button[1]"))) ``` Ekspresi XPath di atas merupakan instruksi untuk mencari sebuah elemen pada dokumen HTML. -`//table[@id='specialties']` mencari elemen `table` dengan atribut `id` bernilai `specialties`. -Kemudian dilanjutkan dengan `/tbody` yang akan mencari elemen `tbody` yang berada di dalam `table`. -Lalu `/tr[1]/td[2]/button[1]` berarti mencari elemen `tr` (baris) pertama di dalam tabel data, -diikuti dengan mencari elemen `td` (kolom) kedua di baris tersebut, -dan diakhiri dengan mencari elemen `button` (tombol) pertama di kolom tersebut. +`//table[@id='specialties']` mencari elemen `<table>` dengan atribut `id` bernilai `specialties`. +Kemudian dilanjutkan dengan `/tbody` yang akan mencari elemen `<tbody>` yang berada di dalam `<table>`. +Lalu `/tr[1]/td[2]/button[1]` berarti mencari elemen `<tr>` (baris) pertama di dalam tabel data, +diikuti dengan mencari elemen `<td>` (kolom) kedua di baris tersebut, +dan diakhiri dengan mencari elemen `<button>` (tombol) pertama di kolom tersebut. Berikut ini adalah daftar referensi terkait XPath yang direkomendasikan: @@ -335,7 +443,8 @@ Berikut ini adalah daftar referensi terkait XPath yang direkomendasikan: ### Latihan Singkat: Membuat Step Definition Baru -> TODO: Tambah pengantar +Mari coba membuat sebuah deskripsi fitur beserta sebuah skenario test baru. +Silakan ikuti _tasks_ berikut: 1. [ ] Buat _class_ Java baru bernama `PetTypeStepDefinitions` di dalam _package_ `stepdefinitions`. 2. [ ] Buat fungsi _step definition_ yang dipetakan ke kalimat `Given` pada skenario test "Add new pet type" @@ -349,7 +458,7 @@ Silakan lihat isi _class_ `SpecialtyStepDefinitions` sebagai referensi. ## Refactoring Pada Deskripsi Fitur & Glue Code -> TODO: Tambah paragraf pengantar, angkat isu DRY (Dont Repeat Yourself) +Mari lihat kembali deskripsi fitur "Manage specialties": ```gherkin Feature: Manage specialties @@ -370,9 +479,12 @@ Kalimat berawalan `Given` muncul berulang kali pada deskripsi fitur di atas karena masing-masing skenario test memiliki kondisi awal SUT yang sama, yaitu aktor membuka laman daftar bidang spesialis dokter hewan. -Untuk mengurangi duplikasi, kita dapat menggunakan kata kunci `Background`. +Untuk mengurangi duplikasi dan menerapkan prinsip DRY ("_Don't Repeat Yourself_") pada kode test, +kita dapat menggunakan kata kunci `Background`. `Background` dapat mengandung kalimat-kalimat yang akan diterapkan ke setiap skenario test di dalam deskripsi fitur. +Sebagai contoh, ubah deskripsi fitur "Manage specialties": + ```gherkin Feature: Manage specialties The veterinarian wants to be able to add, edit, and delete specialties. @@ -405,6 +517,8 @@ Click.on(Link.withText("Pet Types")) ``` Aksi klik menu tersebut dapat digeneralisasi untuk digunakan kembali ketika kita akan menguji fitur lainnya yang dapat diakses melalui _navigation bar_ yang sama. +Sebagai contoh, _class_ Java `NavigationBar` di dalam _package_ `starter.helpers` mengandung sebuah fungsi `clickMenu` yang mengenkapsulasi aksi klik menu. +Contoh kode dari _class_ tersebut dapat dilihat pada potongan kode berikut: ```java package starter.helpers; @@ -425,9 +539,27 @@ public class NavigationBar { } ``` +Aksi klik menu pada _navigation bar_ bisa digantikan dengan pemanggilan fungsi `clickMenu`. +Cari kemunculan dua _statement_ yang menyimulasikan aksi klik menu, +kemudian ganti dengan pemanggilan prosedur yang mengenkapsulasi aksi klik menu tersebut. + +Sebagai contoh: + +```java +// ... +HoverOverBy.over(Link.withText([nama menu])) +Click.on(Link.withText([nama menu])) +// ... + +// Ganti dua statement di atas menjadi +// ... +NavigationBar.clickMenu([nama menu]) +// ... +``` + ### Latihan Singkat: Refactor Aksi Verifikasi Isi Daftar -Lihat kembali fungsi _step definition_ untuk kalimat `Then` fitur "Manage specialties" berikut: +Lihat kembali fungsi _step definition_ untuk kalimat `Then` fitur "Manage specialties": ```java @Then("{actor} should see the pet type {string} on the list of pet types") @@ -463,17 +595,20 @@ public static PerformablePredicate verifyDataItem(String inputFieldNameOrId, Str } ``` -## Latihan Mandiri: Membuat Test Suite BDD Untuk Fitur Lainnya +Apabila telah selesai, simpan hasil pekerjaan. +Buat _commit_ Git dan _push_ ke "_fork_" di GitLab CSUI. -<!-- TODO: Fitur-fitur lainnya ada: Manage Veterinarian, Manage Owner --> -<!-- Buat deskripsi latihannya untuk dikerjakan di hands-on setelah makan siang --> +## Latihan Mandiri: Membuat Test Suite BDD Untuk Fitur Lainnya -<!-- -TODO: -- Klarifikasi perbedaan `wasAbleTo` dan `attemptsTo`. - - Daya: Saya saat ini menduga `wasAbleTo` lebih spesifik digunakan pada step definition @Given karena bertugas untuk menyiapkan preconditions sebelum fitur diujicobakan. ---> +Anda telah mencoba melengkapi deskripsi fitur beserta skenario test untuk dua fitur, +yaitu fitur "Manage specialties" dan "Manage pet type". +Masih ada beberapa fitur lain seperti fitur mengelola data dokter hewan ("Manage veterinarian"), +dan fitur mengelola data pemilik binatang peliharaan ("Manage owner"). +Pada waktu workshop yang tersisa, silakan lengkapi _test suite_ BDD dengan menambahkan deskripsi fitur +dan skenario test bagi fitur-fitur yang belum diuji. [1]: https://docs.google.com/presentation/d/1YQtWa0k45xCsa3Rugt-xfZxUSCg8uoMQepMASh1QEeU?usp=drive_fs [2]: https://gitlab.cs.ui.ac.id/pmpl/workshops/spring-petclinic-bdd/-/blob/development/docker-compose.yml [3]: https://gitlab.cs.ui.ac.id/pmpl/workshops/spring-petclinic-bdd/-/blob/development/src/test/resources/features/veterinarian/manage_specialties.feature +[Spring Petclinic BDD @ GitLab CSUI](https://gitlab.cs.ui.ac.id/pmpl/workshops/spring-petclinic-bdd) +[CucumberTestSuite]: https://gitlab.cs.ui.ac.id/pmpl/workshops/spring-petclinic-bdd/blob/development/src/test/java/starter/CucumberTestSuite.java diff --git a/docs/workshops/images/day_3_-_cucumber_test_suite.png b/docs/workshops/images/day_3_-_cucumber_test_suite.png new file mode 100644 index 0000000000000000000000000000000000000000..bdce91ab62ab862163ddfc96db4cf0788831aede Binary files /dev/null and b/docs/workshops/images/day_3_-_cucumber_test_suite.png differ diff --git a/docs/workshops/images/day_3_-_inspect_element_xpath.png b/docs/workshops/images/day_3_-_inspect_element_xpath.png new file mode 100644 index 0000000000000000000000000000000000000000..b4c08cd56d79884e895cc3fa63f80d5c58958ac3 Binary files /dev/null and b/docs/workshops/images/day_3_-_inspect_element_xpath.png differ diff --git a/docs/workshops/images/day_3_-_serenity_report.png b/docs/workshops/images/day_3_-_serenity_report.png new file mode 100644 index 0000000000000000000000000000000000000000..988fadff8e1cabe5c89a1f973bae681dd850be7f Binary files /dev/null and b/docs/workshops/images/day_3_-_serenity_report.png differ diff --git a/docs/workshops/images/day_3_-_spring_petclinic_front_page.png b/docs/workshops/images/day_3_-_spring_petclinic_front_page.png new file mode 100644 index 0000000000000000000000000000000000000000..636d798e31b1d65d4b61f8a448b90faa95237ef3 Binary files /dev/null and b/docs/workshops/images/day_3_-_spring_petclinic_front_page.png differ diff --git a/docs/workshops/images/workshop_prep_-_docker_desktop_windows.png b/docs/workshops/images/workshop_prep_-_docker_desktop_windows.png new file mode 100644 index 0000000000000000000000000000000000000000..6c4d21f64c3db79dce151b541b0bf38a832fab66 Binary files /dev/null and b/docs/workshops/images/workshop_prep_-_docker_desktop_windows.png differ diff --git a/docs/workshops/prep.md b/docs/workshops/prep.md new file mode 100644 index 0000000000000000000000000000000000000000..f033d739eac59f5a7c9c3c782c631469845a3933 --- /dev/null +++ b/docs/workshops/prep.md @@ -0,0 +1,39 @@ +# Workshop Preparation + +## Docker & Docker Compose + +Silakan ikuti panduan memasang Docker sesuai dengan sistem operasi yang anda gunakan. +Cek panduan pemasangan Docker di tautan berikut: [[klik]](https://docs.docker.com/get-docker/). +Panduan tersebut akan mengarahkan anda untuk memasang aplikasi Docker Desktop. + +Untuk keperluan kegiatan workshop, pastikan instalasi Docker dapat dipanggil melalui _shell_. +Buka _shell_ sistem operasi komputer anda, lalu panggil perintah berikut: + +```shell +docker --version +``` + +Perintah di atas akan mencetak versi instalasi Docker yang terpasang di sistem operasi komputer anda. + +Bagi pengguna sistem operasi Windows, pemanggilan `docker` di _shell_ mungkin gagal apabila aplikasi Docker Desktop belum berjalan. +Silakan jalankan aplikasi Docker Desktop terlebih dahulu kemudian ulang kembali pemanggilan `docker`. +Apabila aplikasi Docker Desktop dipasang secara normal, +_shortcut_ aplikasinya dapat ditemukan di Start Menu Windows seperti pada _screenshot_ berikut: + + + +Berikutnya pastikan _plugin_ Docker Compose sudah termasuk di dalam instalasi Docker di sistem operasi komputer anda. +Buka kembali _shell_ sistem operasi komputer anda, lalu panggil perintah berikut: + +```shell +docker compose version +``` + +Serupa dengan perintah pengecekan versi Docker, perintah di atas akan mencetak versi _plugin_ Docker Compose. + +Apabila anda pernah memasang Docker cukup lama di komputer anda, +ada kemungkinan perintah di atas gagal karena instalasi Docker anda masih menggunakan versi lama. +Pada instalasi Docker versi lama, _plugin_ Docker Compose belum terintegrasi dengan Docker. +Oleh karena itu, anda perlu memperbaharui versi Docker anda ke versi terbaru +atau pasang _plugin_ Docker Compose sebagai program terpisah bernama `docker-compose` yang dapat dipanggil dari _shell_. +Silakan ikuti panduan berikut untuk memasang program `docker-compose` secara terpisah dari program Docker: [[klik]](https://docs.docker.com/compose/install/standalone/). diff --git a/mkdocs.yml b/mkdocs.yml index 6c6097010e6aabd5056a4ed7c1f6493279be6444..e2757376ae02963289a7ea814791626b56fc7eec 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,6 +53,7 @@ nav: - Home: index.md - Workshops: - workshops/index.md + - Preparation: workshops/prep.md - Day 1 - SQA: workshops/day_1_sqa.md - Day 2 - TDD: workshops/day_2_tdd.md - Day 3 - BDD: workshops/day_3_bdd.md