Fakultas Ilmu Komputer UI

Skip to content
Snippets Groups Projects

PMPL Exercise

Rahmania Astrid Mochtar - 1606828702 - PMPL B

Link

my app

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:

  1. Merapikan codebase dengan struktur yang teratur
  2. Memudahkan debugging apabila ada test yang fail
  3. 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.