diff --git a/README.md b/README.md index 942139a6940b2b21bcb5fec628565254347b4a0d..e94df8e8d7956a50fd4a7befcf2155a11c7dfdc5 100644 --- a/README.md +++ b/README.md @@ -70,4 +70,60 @@ Selanjutnya `green` berarti developer membuat production code yang akan membuat Sedangkan `refactor` berarti developer menambahkan atau memodifikasi production code yang sudah dibuat sebelumnya agar code tersebut lebih optimal serta dapat meningkatkan readability dan maintanability. Pada refactor ini biasanya developer akan membersihkan code smells yang ada pada production code, seperti code yang duplicate, method yang terlalu panjang, dan code smells lainnya. Refactor seharusnya tidak mengubah implementasi dari production code yang telah dibuat, namun hanya mengubah bagaimana implementasi tersebut dijalankan dengan lebih rapi. -Test Organizations yang saya lakukan pada exercise 5 ini memberikan kejelasan tentang test mana yang bertanggung jawab pada suatu aktivitas. Test yang dibuat akan menjadi lebih mudah dibaca karena adanya pemisahan pada setiap test yang melakukan aktivitas berbeda. \ No newline at end of file +Test Organizations yang saya lakukan pada exercise 5 ini memberikan kejelasan tentang test mana yang bertanggung jawab pada suatu aktivitas. Test yang dibuat akan menjadi lebih mudah dibaca karena adanya pemisahan pada setiap test yang melakukan aktivitas berbeda. + + +## Exercise 6 + +Pada awalnya fungsi untuk menampilkan comment yang ada pada exercise sebelumnya saya taruh pada html. Kali ini saya memindahkannya pada views seperti berikut: +``` +def view_list(request, list_id, error=''): + list_ = List.objects.get(id=list_id) + items = Item.objects.filter(list=list_) + if len(items) >= 5: + comment = "OH TIDAKKK" + elif len(items) >= 1: + comment = "sibuk tapi santai" + else: + comment = "yey, waktunya berlibur" + + return render(request, 'list.html', {'list': list_, 'items': items, 'comment': comment, 'error': error}) +``` + +Selanjutnya berdasarkan code di atas, saya membuat 2 buah mutant dengan menggunakan Relational Operator Replacement (ROR). Pada mutant pertama saya mengubah code ``if len(items) >= 5`` menjadi ``if len(items) < 5``. Sedangkan pada mutant kedua saya mengubah code ``elif len(items) >= 1`` menjadi ``elif len(items) == 1``. + +Test case baru yang saya buat untuk meng-kill kedua mutant di atas adalah sebagai berikut: +``` + def test_comment_only_for_no_todo(self): + list_ = List.objects.create() + response = self.client.get(f'/lists/{list_.id}/') + self.assertEqual(Item.objects.count(), 0) + self.assertIn('yey, waktunya berlibur', response.content.decode()) + + def test_comment_only_for_todo_morethan_5(self): + list_ = List.objects.create() + for i in range(6): + Item.objects.create(text='itemey {}'.format(i), list=list_) + response = self.client.get(f'/lists/{list_.id}/') + self.assertIn('OH TIDAKKK', response.content.decode()) + + def test_comment_only_for_todo_lessthan_5(self): + list_ = List.objects.create() + for i in range(2): + Item.objects.create(text='itemey {}'.format(i), list=list_) + response = self.client.get(f'/lists/{list_.id}/') + self.assertIn('sibuk tapi santai', response.content.decode()) +``` + +### Django Mutpy + +Selanjutnya saya melakukan mutation testing dengan menggunakan django-mutpy. Dengan command ``python manage.py muttest lists --modules lists.views lists.models`` didapatkan hasil sebagai berikut: +``` +[0.08386 s] killed by test_root_url_resolves_to_home_page_view (lists.tests.test_views.HomePageTest) +[*] Mutation score [7.21336 s]: 100.0% + - all: 41 + - killed: 41 (100.0%) + - survived: 0 (0.0%) + - incompetent: 0 (0.0%) + - timeout: 0 (0.0%) +``` \ No newline at end of file diff --git a/lists/templates/base.html b/lists/templates/base.html index 2bf1850a4edff889eaa1e73a113f027214d723bf..87296be4577ebcb191e90f8b0df58d07aeb5111d 100644 --- a/lists/templates/base.html +++ b/lists/templates/base.html @@ -56,4 +56,4 @@ - \ No newline at end of file + diff --git a/lists/templates/list.html b/lists/templates/list.html index df0238fd8db9a277ee2bf66f8c59cfe188bc3073..27076ab32288721a5ead157d65883fe06d5bf8eb 100644 --- a/lists/templates/list.html +++ b/lists/templates/list.html @@ -14,12 +14,6 @@ {% block comment %}
- {% if list.item_set.all.count >= 5 %} -

OH TIDAKKK

- {% elif list.item_set.all.count >= 1 %} -

sibuk tapi santai

- {% else %} -

yey, waktunya berlibur

- {% endif %} + {{ comment }}
{% endblock %} \ No newline at end of file diff --git a/lists/tests/test_views.py b/lists/tests/test_views.py index ee5026240c1efe7ddc935e7d4b732ff126eeae50..8a062ad9fc397b3bdc7f66e0b0092e562e7ddc1b 100644 --- a/lists/tests/test_views.py +++ b/lists/tests/test_views.py @@ -19,24 +19,44 @@ class HomePageTest(TestCase): html = response.content.decode('utf8') self.assertTrue(html.startswith('')) self.assertIn('Aviliani\'s Homepage', html) - self.assertTrue(html.endswith('')) + self.assertTrue(html.strip().endswith('')) def test_uses_home_template(self): response = self.client.get('/') self.assertTemplateUsed(response, 'index.html') - def test_displays_automated_comment(self): - cases = [ - (0, "yey, waktunya berlibur"), - (1, "sibuk tapi santai"), - (4, "OH TIDAKKK") - ] + # def test_displays_automated_comment(self): + # cases = [ + # (0, "yey, waktunya berlibur"), + # (1, "sibuk tapi santai"), + # (4, "OH TIDAKKK") + # ] + # list_ = List.objects.create() + # for n, comment in cases: + # for i in range(n): + # Item.objects.create(text='itemy {}'.format(i), list=list_) + # response = self.client.get(f'/lists/{list_.id}/') + # self.assertIn(comment, response.content.decode()) + + def test_comment_only_for_no_todo(self): list_ = List.objects.create() - for n, comment in cases: - for i in range(n): - Item.objects.create(text='itemy {}'.format(i), list=list_) - response = self.client.get(f'/lists/{list_.id}/') - self.assertIn(comment, response.content.decode()) + response = self.client.get(f'/lists/{list_.id}/') + self.assertEqual(Item.objects.count(), 0) + self.assertIn('yey, waktunya berlibur', response.content.decode()) + + def test_comment_only_for_todo_morethan_5(self): + list_ = List.objects.create() + for i in range(6): + Item.objects.create(text='itemey {}'.format(i), list=list_) + response = self.client.get(f'/lists/{list_.id}/') + self.assertIn('OH TIDAKKK', response.content.decode()) + + def test_comment_only_for_todo_lessthan_5(self): + list_ = List.objects.create() + for i in range(2): + Item.objects.create(text='itemey {}'.format(i), list=list_) + response = self.client.get(f'/lists/{list_.id}/') + self.assertIn('sibuk tapi santai', response.content.decode()) def test_home_page_contains_name(self): request = HttpRequest() diff --git a/lists/views.py b/lists/views.py index d4c61b1bf2c87e241fe49c6aac51a9f127474f8a..b9131e191fb5f76d06aa7f83d6ac892fad8ca086 100644 --- a/lists/views.py +++ b/lists/views.py @@ -10,7 +10,15 @@ def home_page(request, error=''): def view_list(request, list_id, error=''): list_ = List.objects.get(id=list_id) items = Item.objects.filter(list=list_) - return render(request, 'list.html', {'list': list_,'items': items, 'error': error}) + if len(items) >= 5: + comment = "OH TIDAKKK" + elif len(items) >= 1: + comment = "sibuk tapi santai" + else: + comment = "yey, waktunya berlibur" + + return render(request, 'list.html', {'list': list_, 'items': items, 'comment': comment, 'error': error}) + def new_list(request): if (len(request.POST['item_text']) == 0): diff --git a/requirements.txt b/requirements.txt index b2c9fc6f1fee3d7a84610b3117b3bbe7fa057504..e0377262c149860db467058ed6846c2e3bf1265a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,17 @@ +astmonkey==0.3.6 dj-database-url==0.5.0 Django==1.11.24 +django-mutpy==0.1.2 gunicorn==19.9.0 +Jinja2==2.10.3 +MarkupSafe==1.1.1 +MutPy==0.6.0 psycopg2==2.8.3 +pydot==1.4.1 +pyparsing==2.4.4 pytz==2019.2 +PyYAML==5.1.2 selenium==3.141.0 +termcolor==1.1.0 urllib3==1.25.3 whitenoise==4.1.3 diff --git a/superlists/settings.py b/superlists/settings.py index b28ce15c67c0762b6b07f77b3542990f480868c0..736f5e2bdea8631b1b618b3926d1b154fc9e345d 100644 --- a/superlists/settings.py +++ b/superlists/settings.py @@ -38,6 +38,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django_mutpy', 'lists', ]