Fakultas Ilmu Komputer UI

Commit 82171e55 authored by Rahmania Astrid Mochtar's avatar Rahmania Astrid Mochtar
Browse files

Mutationtesting

parent fdeac8a1
......@@ -150,4 +150,51 @@ Dalam pembuatan test, diprioritaskan agar implementasi dapat pass test tersebut.
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
\ No newline at end of file
3. Memudahkan proses pembuatan test untuk fitur tertentu
## Exercise 6
### Mutation Testing
Penambahan mutan pada kode dalam `lists.views`:
```diff
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`.
```bash
pip3 install django-mutpy
```
Lalu jalankan mutation test dengan memasukkan command `muttest`
```bash
python3 manage.py muttest lists --modules lists.views
```
Hasil dari mutation testing
```bash
[*] 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.
\ No newline at end of file
......@@ -48,6 +48,7 @@
</div>
</div>
<h5>{{ comment }}</h5>
</div>
</body>
</html>
\ No newline at end of file
......@@ -10,14 +10,7 @@
<tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr>
{% endfor %}
</table>
{% if list.item_set.all|length == 0 %}
<h5>yey, waktunya berlibur</h5>
{% elif list.item_set.all|length < 5 %}
<h5>sibuk tapi santai</h5>
{% else %}
<h5>oh tidak</h5>
{% endif %}
{% endblock %}
......@@ -67,34 +67,34 @@ class ListViewTest(TestCase):
self.assertEqual(response.context['list'], correct_list)
# def test_automated_comment_if_list_empty(self):
# response = self.client.get('/lists/the-only-list-in-the-world/')
# response = self.client.get('/')
# self.assertIn(
# 'yey, waktunya berlibur',
# response.content.decode()
# )
# def test_automated_comment_if_list_less_than_5(self):
# list_ = List.objects.create()
# create_items(2, list_)
def test_automated_comment_if_list_less_than_5(self):
list_ = List.objects.create()
create_items(2, list_)
# response = self.client.get('/lists/the-only-list-in-the-world/')
response = self.client.get(f'/lists/{list_.id}/')
# self.assertIn(
# 'sibuk tapi santai',
# response.content.decode()
# )
self.assertIn(
'sibuk tapi santai',
response.content.decode()
)
# def test_automated_comment_if_list_5_or_more(self):
# list_ = List.objects.create()
# create_items(5, list_)
def test_automated_comment_if_list_5_or_more(self):
list_ = List.objects.create()
create_items(5, list_)
# response = self.client.get('/lists/the-only-list-in-the-world/')
response = self.client.get(f'/lists/{list_.id}/')
# self.assertIn(
# 'oh tidak',
# response.content.decode()
# )
self.assertIn(
'oh tidak',
response.content.decode()
)
class NewListTest(TestCase):
......
......@@ -7,10 +7,19 @@ from lists.models import Item, List
def home_page(request):
return render(request, 'home.html')
def generate_comment(list_):
length = list_.item_set.count()
if length == 0:
return "yey, waktunya berlibur"
elif length < 5:
return "sibuk tapi santai"
else:
return "oh tidak"
def view_list(request, list_id):
list_ = List.objects.get(id=list_id)
return render(request, 'list.html', {'list': list_})
comment = generate_comment(list_)
return render(request, 'list.html', {'list': list_, 'comment': comment })
def new_list(request):
......
......@@ -41,6 +41,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_mutpy',
'lists'
]
......@@ -79,9 +80,19 @@ WSGI_APPLICATION = 'superlists.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASE_URL = 'postgres://zrcgjeyohzggpw:7310e5d8c03d5e4ec62247a9bfc04a608bc4ad045c7618ee1a06109be6768a5b@ec2-23-21-160-80.compute-1.amazonaws.com:5432/d2qi0m4m9s14o6'
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES = {'default': dj_database_url.config(default=DATABASE_URL)}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
PRODUCTION = os.environ.get('DATABASE_URL') != None
if PRODUCTION:
# DATABASE_URL = 'postgres://zrcgjeyohzggpw:7310e5d8c03d5e4ec62247a9bfc04a608bc4ad045c7618ee1a06109be6768a5b@ec2-23-21-160-80.compute-1.amazonaws.com:5432/d2qi0m4m9s14o6'
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES['default'] = dj_database_url.config()
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment