Fakultas Ilmu Komputer UI

Commit ff354ea9 authored by Rayza Arasj Mahardhika's avatar Rayza Arasj Mahardhika
Browse files

Merge branch 'exercise-6' into 'master'

Exercise 6

See merge request !5
parents f3686cef c06edc47
Pipeline #24101 failed with stage
in 1 minute and 22 seconds
......@@ -52,3 +52,57 @@ Red, Green, Refactor adalah tahapan-tahapan yang ada pada TDD (Test Driven Devel
### Jelaskan keuntungan yang dapat kita dapatkan dengan menrapkan Test Organization.
Dengan menerapkan Test Organization, test yang kita miliki akan tersusun rapih. Berbeda dengan sebelum melakukan Latihan 5, test yang ada pada repo Latihan ini hanya berada di satu file baik untuk functional_test ataupun unit_test. Hal ini akan menjadi code smell jika file yang kita miliki semakin panjang. Oleh karena itu diperlukan Test Organization agar test yang kita miliki tetap maintainable dan tidak menimbulkan code smell. Dengan pemisahan file test ini juga kita jadi dapat memilih file mana saja yang ingin kita jalankan testnya, dimana sebelumnya jika kita ingin melakukan test hanya pada suatu fungsi, kita harus menjalankan semua test yang ada pada file tersebut.
## Exercise - 6 : Mutation
### Mutasi 1 : Relational Operator Replacement
Pada mutasi peratama ini saya menggunakan mutasi Relational Operator Replacement (ROR) dimana mutasi ini mengubah operator perbandingan, dari `<` menjadi `<=`. Saya membuat test dimana mengecek case khusus sepert `item_count` 5, dimana seharusnya mengembalikan `oh tidak`.
Code:
```
def get_commentary(item_count):
if (item_count == 0):
return COMMENTARY_ZERO
elif (item_count <= 5):
return COMMENTARY_LESS_THAN_FIVE
elif (item_count >= 5):
return COMMENTARY_MORE_THAN_EQUAL_FIVE
```
Test:
```
def test_commentary_correct_count_5_correct(self):
result = get_commentary(5)
self.assertEqual(result, COMMENTARY_MORE_THAN_EQUAL_FIVE)
```
### Mutasi 2 : Scalar Variable Replacement
Pada mutasi kedia ini saya menggunakan mutasi Scalar Variable Replacement (SVR) dimana mutasi ini mengubah variable yang digunakan pada suatu line code, pada mutasi ini saya mengganti variable `COMMENTARY_LESS_THAN_FIVE` menjadi `COMMENTARY_MORE_THAN_EQUAL_FIVE`. Saya membuat test dimana mengecek penggunaan variable tersebut.
Code:
```
def get_commentary(item_count):
if (item_count == 0):
return COMMENTARY_ZERO
elif (item_count < 5):
return COMMENTARY_MORE_THAN_EQUAL_FIVE
elif (item_count >= 5):
return COMMENTARY_MORE_THAN_EQUAL_FIVE
```
Test:
```
def test_commentary_correct_count_less_than_5_correct(self):
result = get_commentary(4)
self.assertEqual(result, COMMENTARY_LESS_THAN_FIVE)
```
### Mutation Tool (django-mutpy)
Setelah saya menggunakan django-mutpy untuk pertama kali (hasil dapat dilihat di file `mutation_test.result`), terdapat 46 mutasi yang survived dan 6 mutasi yang timeout. Mutasi yang survived mayoritas meruapakan mutasi pada migration file, sedangkan mutasi yang timeout semuanya karena mutasi AOR pada penjumlahan string yang memang akan membuat file gagal.
### After Mutation Tool (django-mutpy)
Setelah melihat hasil pada file `mutation_test.result`, saya melihat terdapat mutasi yang survived pada file `apps.py`. Hal ini dikarenakan memang belum ada test yang dibuat untuk melakukan test pada file `apps.py`. Oleh karena itu saya menambahkan test berikut pada file `test_apps.py`:
```
def test_apps(self):
self.assertEqual(ListsConfig.name, 'lists')
self.assertEqual(apps.get_app_config('lists').name, 'lists')
```
Dengan test tersebut jumlah mutant yang survived berkurang menjadi 44 karena terdapat 2 mutant yang berhasil di kill. (hasil baru dapat dilihat di file `mutation_test_after.result`)
\ No newline at end of file
from django.apps import apps
from django.test import TestCase
from lists.apps import ListsConfig
class ListsConfigTest(TestCase):
def test_apps(self):
self.assertEqual(ListsConfig.name, 'lists')
self.assertEqual(apps.get_app_config('lists').name, 'lists')
\ No newline at end of file
......@@ -3,7 +3,7 @@ from django.test import TestCase
from django.http import HttpRequest
from django.utils.html import escape
from lists.views import home_page, about_page, \
COMMENTARY_ZERO, COMMENTARY_LESS_THAN_FIVE, COMMENTARY_MORE_THAN_EQUAL_FIVE
COMMENTARY_ZERO, COMMENTARY_LESS_THAN_FIVE, COMMENTARY_MORE_THAN_EQUAL_FIVE, get_commentary
from lists.models import Item, List
......@@ -126,3 +126,13 @@ class NewListTest(TestCase):
self.client.post('/lists/new', data={'item_text': ''})
self.assertEqual(List.objects.count(), 0)
self.assertEqual(Item.objects.count(), 0)
class CustomTest(TestCase):
def test_commentary_correct_count_5_correct(self):
result = get_commentary(5)
self.assertEqual(result, COMMENTARY_MORE_THAN_EQUAL_FIVE)
def test_commentary_correct_count_less_than_5_correct(self):
result = get_commentary(4)
self.assertEqual(result, COMMENTARY_LESS_THAN_FIVE)
\ No newline at end of file
[*] Start mutation process:
- targets: lists.admin, lists.apps, lists.migrations.0001_initial, lists.migrations.0002_item_text, lists.migrations.0003_list, lists.migrations.0004_item_list, lists.models, lists.tests.test_models, lists.tests.test_views, lists.urls, lists.views
- tests: lists.tests
[*] 17 tests passed:
- lists.tests.test_models [0.01265 s]
- lists.tests.test_views [0.10589 s]
[*] Start mutants generation and execution:
- [# 1] CRP lists.apps:
--------------------------------------------------------------------------------
1: from django.apps import AppConfig
2:
3:
4: class ListsConfig(AppConfig):
- 5: name = 'lists'
+ 5: name = 'mutpy'
--------------------------------------------------------------------------------
[0.12771 s] survived
- [# 2] CRP lists.apps:
--------------------------------------------------------------------------------
1: from django.apps import AppConfig
2:
3:
4: class ListsConfig(AppConfig):
- 5: name = 'lists'
+ 5: name = ''
--------------------------------------------------------------------------------
[0.12091 s] survived
- [# 3] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
11:
12:
13: operations = [\
14: migrations.CreateModel(name=\
- 15: 'Item', fields=\
+ 15: 'mutpy', fields=\
16: [\
17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.17170 s] survived
- [# 4] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
11:
12:
13: operations = [\
14: migrations.CreateModel(name=\
- 15: 'Item', fields=\
+ 15: '', fields=\
16: [\
17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.12439 s] survived
- [# 5] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.CreateModel(name=\
15: 'Item', fields=\
16: [\
- 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 17: ('mutpy', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.12319 s] survived
- [# 6] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.CreateModel(name=\
15: 'Item', fields=\
16: [\
- 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 17: ('', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.13921 s] survived
- [# 7] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.CreateModel(name=\
15: 'Item', fields=\
16: [\
- 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='mutpy'))])]
--------------------------------------------------------------------------------
[0.12224 s] survived
- [# 8] CRP lists.migrations.0001_initial:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.CreateModel(name=\
15: 'Item', fields=\
16: [\
- 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name=''))])]
--------------------------------------------------------------------------------
[0.11713 s] survived
- [# 9] IHD lists.migrations.0001_initial:
--------------------------------------------------------------------------------
4:
5:
6: class Migration(migrations.Migration):
7:
- 8: initial = True
+ 8: pass
9:
10: dependencies = []
11:
12:
--------------------------------------------------------------------------------
[0.11917 s] survived
- [# 10] IHD lists.migrations.0001_initial:
--------------------------------------------------------------------------------
6: class Migration(migrations.Migration):
7:
8: initial = True
9:
- 10: dependencies = []
+ 10: pass
11:
12:
13: operations = [\
14: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.13458 s] survived
- [# 11] IHD lists.migrations.0001_initial:
--------------------------------------------------------------------------------
9:
10: dependencies = []
11:
12:
- 13: operations = [\
- 14: migrations.CreateModel(name=\
- 15: 'Item', fields=\
- 16: [\
- 17: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 13: pass
--------------------------------------------------------------------------------
[0.11825 s] survived
- [# 12] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0001_initial')]
+ 9: ('mutpy', '0001_initial')]
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11342 s] survived
- [# 13] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0001_initial')]
+ 9: ('', '0001_initial')]
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11551 s] survived
- [# 14] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0001_initial')]
+ 9: ('lists', 'mutpy')]
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11424 s] survived
- [# 15] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0001_initial')]
+ 9: ('lists', '')]
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11202 s] survived
- [# 16] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
- 14: 'item', name=\
+ 14: 'mutpy', name=\
15: 'text', field=\
16: models.TextField(default=''))]
--------------------------------------------------------------------------------
[0.11284 s] survived
- [# 17] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
- 14: 'item', name=\
+ 14: '', name=\
15: 'text', field=\
16: models.TextField(default=''))]
--------------------------------------------------------------------------------
[0.11248 s] survived
- [# 18] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
11:
12: operations = [\
13: migrations.AddField(model_name=\
14: 'item', name=\
- 15: 'text', field=\
+ 15: 'mutpy', field=\
16: models.TextField(default=''))]
--------------------------------------------------------------------------------
[0.11233 s] survived
- [# 19] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
11:
12: operations = [\
13: migrations.AddField(model_name=\
14: 'item', name=\
- 15: 'text', field=\
+ 15: '', field=\
16: models.TextField(default=''))]
--------------------------------------------------------------------------------
[0.11289 s] survived
- [# 20] CRP lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
12: operations = [\
13: migrations.AddField(model_name=\
14: 'item', name=\
15: 'text', field=\
- 16: models.TextField(default=''))]
+ 16: models.TextField(default='mutpy'))]
--------------------------------------------------------------------------------
[0.11296 s] survived
- [# 21] IHD lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
4:
5:
6: class Migration(migrations.Migration):
7:
- 8: dependencies = [\
- 9: ('lists', '0001_initial')]
+ 8: pass
+ 9:
10:
11:
12: operations = [\
13: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11444 s] survived
- [# 22] IHD lists.migrations.0002_item_text:
--------------------------------------------------------------------------------
8: dependencies = [\
9: ('lists', '0001_initial')]
10:
11:
- 12: operations = [\
- 13: migrations.AddField(model_name=\
- 14: 'item', name=\
- 15: 'text', field=\
- 16: models.TextField(default=''))]
+ 12: pass
--------------------------------------------------------------------------------
[0.11129 s] survived
- [# 23] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0002_item_text')]
+ 9: ('mutpy', '0002_item_text')]
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.11187 s] survived
- [# 24] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0002_item_text')]
+ 9: ('', '0002_item_text')]
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.11047 s] survived
- [# 25] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0002_item_text')]
+ 9: ('lists', 'mutpy')]
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.10881 s] survived
- [# 26] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
5:
6: class Migration(migrations.Migration):
7:
8: dependencies = [\
- 9: ('lists', '0002_item_text')]
+ 9: ('lists', '')]
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.11065 s] survived
- [# 27] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
- 14: 'List', fields=\
+ 14: 'mutpy', fields=\
15: [\
16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.12857 s] survived
- [# 28] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
- 14: 'List', fields=\
+ 14: '', fields=\
15: [\
16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.11497 s] survived
- [# 29] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
12: operations = [\
13: migrations.CreateModel(name=\
14: 'List', fields=\
15: [\
- 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 16: ('mutpy', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.11940 s] survived
- [# 30] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
12: operations = [\
13: migrations.CreateModel(name=\
14: 'List', fields=\
15: [\
- 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 16: ('', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
--------------------------------------------------------------------------------
[0.15473 s] survived
- [# 31] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
12: operations = [\
13: migrations.CreateModel(name=\
14: 'List', fields=\
15: [\
- 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='mutpy'))])]
--------------------------------------------------------------------------------
[0.13955 s] survived
- [# 32] CRP lists.migrations.0003_list:
--------------------------------------------------------------------------------
12: operations = [\
13: migrations.CreateModel(name=\
14: 'List', fields=\
15: [\
- 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name=''))])]
--------------------------------------------------------------------------------
[0.11367 s] survived
- [# 33] IHD lists.migrations.0003_list:
--------------------------------------------------------------------------------
4:
5:
6: class Migration(migrations.Migration):
7:
- 8: dependencies = [\
- 9: ('lists', '0002_item_text')]
+ 8: pass
+ 9:
10:
11:
12: operations = [\
13: migrations.CreateModel(name=\
--------------------------------------------------------------------------------
[0.11242 s] survived
- [# 34] IHD lists.migrations.0003_list:
--------------------------------------------------------------------------------
8: dependencies = [\
9: ('lists', '0002_item_text')]
10:
11:
- 12: operations = [\
- 13: migrations.CreateModel(name=\
- 14: 'List', fields=\
- 15: [\
- 16: ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'))])]
+ 12: pass
--------------------------------------------------------------------------------
[0.11429 s] survived
- [# 35] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
6:
7: class Migration(migrations.Migration):
8:
9: dependencies = [\
- 10: ('lists', '0003_list')]
+ 10: ('mutpy', '0003_list')]
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.15293 s] survived
- [# 36] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
6:
7: class Migration(migrations.Migration):
8:
9: dependencies = [\
- 10: ('lists', '0003_list')]
+ 10: ('', '0003_list')]
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.11958 s] survived
- [# 37] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
6:
7: class Migration(migrations.Migration):
8:
9: dependencies = [\
- 10: ('lists', '0003_list')]
+ 10: ('lists', 'mutpy')]
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.13089 s] survived
- [# 38] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
6:
7: class Migration(migrations.Migration):
8:
9: dependencies = [\
- 10: ('lists', '0003_list')]
+ 10: ('lists', '')]
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
--------------------------------------------------------------------------------
[0.12923 s] survived
- [# 39] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
- 15: 'item', name=\
+ 15: 'mutpy', name=\
16: 'list', field=\
17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
--------------------------------------------------------------------------------
[0.12892 s] survived
- [# 40] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
11:
12:
13: operations = [\
14: migrations.AddField(model_name=\
- 15: 'item', name=\
+ 15: '', name=\
16: 'list', field=\
17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
--------------------------------------------------------------------------------
[0.13558 s] survived
- [# 41] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
12:
13: operations = [\
14: migrations.AddField(model_name=\
15: 'item', name=\
- 16: 'list', field=\
+ 16: 'mutpy', field=\
17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
--------------------------------------------------------------------------------
[0.11523 s] survived
- [# 42] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
12:
13: operations = [\
14: migrations.AddField(model_name=\
15: 'item', name=\
- 16: 'list', field=\
+ 16: '', field=\
17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
--------------------------------------------------------------------------------
[0.10931 s] survived
- [# 43] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.AddField(model_name=\
15: 'item', name=\
16: 'list', field=\
- 17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
+ 17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='mutpy'))]
--------------------------------------------------------------------------------
[0.13076 s] survived
- [# 44] CRP lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
13: operations = [\
14: migrations.AddField(model_name=\
15: 'item', name=\
16: 'list', field=\
- 17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='lists.List'))]
+ 17: models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=''))]
--------------------------------------------------------------------------------
[0.12742 s] survived
- [# 45] IHD lists.migrations.0004_item_list:
--------------------------------------------------------------------------------
5:
6:
7: class Migration(migrations.Migration):
8:
- 9: dependencies = [\