PMPL Exercise
Rahmania Astrid Mochtar - 1606828702 - PMPL B
Link
Exercise 3
Test Isolation
Sebelumnya dalam menggunakan functional_tests.py, test tersebut meninggalkan data-data yang digunakan pada database asli sehingga mempengaruhi hasil test berikutnya.
Dalam Django, terdapat class bernama LiveServerTestCase yang dapat secara otomatis men-setup dan membersihkan database untuk testing.
Perbedaan Design Pada Test
Sebelumnya, class test pada aplikasi menggunakan unitTest.TestCase sebagai berikut:
from django.test import LiveServerTestCase
class NewVisitorTest(LiveServerTestCase):
[...]
Sementara setelah test isolation menjadi:
import unittest
class NewVisitorTest(unitTest.TestCase):
[...]
Dengan adanya LiveServerTestCase, url yang diakses dapat diganti dari yang hardcoded:
def test_can_start_a_list_and_retrieve_it_later(self):
# Edith has heard about a cool new online to-do app. She goes
# to check out its homepage
self.browser.get('https://localhost:8000')
[...]
jadi menggunakan variabel bawaan LiveServerTestCase, yaitu live_server_url:
def test_can_start_a_list_and_retrieve_it_later(self):
# Edith has heard about a cool new online to-do app. She goes
# to check out its homepage
self.browser.get(self.live_server_url)
[...]
Dan karena sekarang digunakan Django test runner untuk menjalankan functional test, maka bagian kode dibawah dapat dihalangkan, yaitu:
if __name__ == '__main__':
unittest.main(warnings='ignore')
Exercise 4
Functional Test-Friendly CSS
Dalam melakukan styling, hal yang perlu diperhatikan adalah konsistensi. Saat diberi functional test dibawah
[...]
inputbox.send_keys('testing')
inputbox.send_keys(Keys.ENTER)
self.wait_for_row_in_list_table('1: testing')
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertAlmostEqual(
inputbox.location['x'] + inputbox.size['width'] / 2,
512,
delta=10
)
Test ingin mengetahui apakah benar input kita di tengah web page. Bentuk home.html
kita seperti dibawah tidak cukup karena tidak menghandle styling di page /lists/{id}
.
[...]
<form method="POST" action="/lists/new">
<p style="text-align: center;">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />
</p>
{% csrf_token %}
</form>
Sehingga kita dapat menggunakan Django Template Inheritance dan CSS Framework seperti Bootstrap.
Contohnya dengan kodingan dibawah adalah penggunaan Bootstrap dalam base.html
hasil template inheritance.
[...]
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
<input name="item_text" id="id_new_item"
placeholder="Enter a to-do item" />
{% csrf_token %}
</form>
</div>
</div>
</div>
Keterhubungan Perubahan Kode
Dalam exercise kali ini, kita telah menambahkan banyak file static yang diperlukan untuk styling aplikasi. Command runserver
dapat mencari file-file static tersebut secara otomatis. Namun LiveServerTestCase
tidak dapat menemukannya, oleh karena itu perlu diubah dengan StaticLiveServerTestCase
.
Sebelumnya:
from django.test import LiveServerTestCase
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.keys import Keys
import time
MAX_WAIT = 10
class NewVisitorTest(LiveServerTestCase):
def setUp(self):
[...]
Menjadi:
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.keys import Keys
import time
MAX_WAIT = 10
class NewVisitorTest(StaticLiveServerTestCase):
def setUp(self):
[...]
Exercise 5
Keterkaitan Refactoring (Red, Green, Refactor) dengan konsep Clean Code
Dalam pembuatan test, diprioritaskan agar implementasi dapat pass test tersebut. Namun ini dapat menyebabkan code smells serta fungsi-fungsi redundan muncul dalam codebase. Untuk menghilangkan masalah-masalah tersebut, maka perlu adanya refactoring. Dengan menghilangkan code smells dan fungsi-fungsi redundan tersebut, kita telah menerapkan konsep clean code DRY (Don't Repeat Yourself), KISS (Keep It Simple Stupid), dan YAGNI (You Aren't Gonna Need It).
Keuntungan Menerapkan Test Organization
Test Organization memiliki beberapa keuntungan yaitu:
- Merapikan codebase dengan struktur yang teratur
- Memudahkan debugging apabila ada test yang fail
- Memudahkan proses pembuatan test untuk fitur tertentu
Exercise 6
Mutation Testing
Penambahan mutan pada kode dalam lists.views
:
def generate_comment(list_):
length = list_.item_set.count()
- if length == 0:
+ if length != 0: // mutan1
return "yey, waktunya berlibur"
- elif length < 5:
+ elif length > 5: // mutan2
return "sibuk tapi santai"
else:
return "oh tidak"
Menggunakan test case yang sudah ada sebelumnya, test case test_automated_comment_if_list_empty
berhasil strongly kill mutan1 saat diberikan list dengan ukuran bukan 0. Sementara test_automated_comment_if_list_less_than_5
berhasil strongly kill mutan2 saat diberikan list dengan ukuran lebih dari 5.
Implementasi Mutation Testing dengan django-mutpy
Untuk mempermudah mutation testing, dapat digunakan tool khusus mutation testing dalam Python dan Django. Saya menggunakan django-mutpy
. Yang dilakukan oleh django-mutpy adalah menambahkan mutan pada tiap fungsi yang ditemukan dengan jenis mutan yang bervariasi; seperti ROR, CRP, COI, dan seterusnya.
Pertama install django-mutpy
menggunakan pip
.
pip3 install django-mutpy
Lalu jalankan mutation test dengan memasukkan command muttest
python3 manage.py muttest lists --modules lists.views
Hasil dari mutation testing
[*] Mutation score [5.43119 s]: 100.0%
- all: 33
- killed: 33 (100.0%)
- survived: 0 (0.0%)
- incompetent: 0 (0.0%)
- timeout: 0 (0.0%)
Karena mutation score dari test adalah 100%, maka tidak perlu menambahkan test case baru untuk menambahkan kualitas.