Fakultas Ilmu Komputer UI

Commit ecfbbd2e authored by Muhammad Ilham Peruzzi's avatar Muhammad Ilham Peruzzi
Browse files

Selesai exercise8 - part 2

parent c6cad1f2
Pipeline #25352 passed with stages
in 8 minutes and 43 seconds
......@@ -13,6 +13,7 @@ Test:
- python3 manage.py makemigrations
- python3 manage.py migrate
- python3 manage.py test lists
- python3 manage.py test accounts
tags:
- test
......
......@@ -148,4 +148,32 @@ Pada saat membuat suatu test case, terkadang kita ingin melakukan test terhadap
Saat melakukan mocking secara manual, kita menggantikan fungsi yang akan ditest dengan mock yang kita buat sendiri. Teknik ini dinamakan monkeypatching, dimana kita memodifikasi fungsi agar sesuai dengan alur program dengan data-data yang bersifat local (hanya berjalan saat test). Melakukan mocking manual harus dilakukan sebelum fungsi yang ingin di test dipanggil, agar fungsi original dapat diganti terlebih dahulu dengan mock yang dibuat.
Berbeda dengan mocking manual, saat melakukan mocking dengan library kita tidak perlu melakukan setup mock sendiri, dikarenakan sudah ada library yang menyediakan dan mempersiapkan mock tersebut, sehingga kita hanya mengatur return value apa dan bagaimana mock tersebut berjalan. Salah satu library mock adalah unittest.mock dan unittest.patch yang terdapat pada Python 3.3.
\ No newline at end of file
Berbeda dengan mocking manual, saat melakukan mocking dengan library kita tidak perlu melakukan setup mock sendiri, dikarenakan sudah ada library yang menyediakan dan mempersiapkan mock tersebut, sehingga kita hanya mengatur return value apa dan bagaimana mock tersebut berjalan. Salah satu library mock adalah unittest.mock dan unittest.patch yang terdapat pada Python 3.3.
## Alasan Mocking Menyebabkan Tightly Coupled
Penggunaan mocking memang sangat membantu dalam melakukan testing fungsi yang menggunakan eksternal framework. Namun, penggunaan mock bisa menyebabkan Tightly Coupled to Implementation. Hal ini disebabkan karena saat membuat mock up kita harus mengatur dan menyesuaikan mock yang dibuat dengan implementasi yang ada pada business logic (dalam hal ini views.py atau file lain yang berisi logic program). Sementara itu, mungkin saja framework yang digunakan memiliki lebih dari satu cara implementasi dengan output yang sama, sehingga mungkin program memberikan output yang sama dengan implementasi berbeda namun mocking test nya menjadi rusak. Contohnya pada implementasi mocking yang dibuat adalah sebagai berikut:
(accounts/tests/test_view.py)
```bash
@patch('accounts.views.messages')
def test_adds_success_message_with_mocks(self, mock_messages, mock_auth):
response = self.client.post('/accounts/send_login_email', data={
'email': 'edith@example.com'
})
expected = "Check your email, we've sent you a link you can use to log in."
self.assertEqual(
mock_messages.success.call_args,
call(response.wsgi_request, expected),
)
```
Pada mock tersebut, kita melakukan mocking pada implementasi messages.success. Namun, framework Django mengizinkan implementasi penggunaan message yang lain untuk message.success dengan menggunakan message.add_message(...). Contohnya adalah sebagai berikut:
```bash
messages.add_message(
request,
messages.SUCCESS,
"Check your email, we've sent you a link you can use to log in."
)
```
Kedua implementasi tersebut, yaitu penggunaan message_success atau message.add_message akan memberikan output yang sama. Namun, dikarenakan mock yang dibuat terikat dengan message.success, maka mock yang dibuat akan rusak jika kita menggunakan implementasi message.add_message, sehingga mocking tersebut sangat bergantung pada bagaimana kita melakukan implementasi program tersebut (tightly coupled with the implementation).
\ No newline at end of file
from django.db import models
import uuid
from django.contrib import auth
from django.db import models
auth.signals.user_logged_in.disconnect(auth.models.update_last_login)
class User(models.Model):
email = models.EmailField(primary_key=True)
......
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.contrib import auth
from accounts.models import Token
User = get_user_model()
User = auth.get_user_model()
class UserModelTest(TestCase):
......@@ -15,6 +14,12 @@ class UserModelTest(TestCase):
user = User(email='a@b.com')
self.assertEqual(user.pk, 'a@b.com')
def test_no_problem_with_auth_login(self):
user = User.objects.create(email='edith@example.com')
user.backend = ''
request = self.client.request().wsgi_request
auth.login(request, user) # should not raise
class TokenModelTest(TestCase):
def test_links_user_with_auto_generated_uid(self):
......
from django.conf.urls import url
from accounts import views
from django.contrib.auth import logout
urlpatterns = [
url(r'^send_login_email$', views.send_login_email, name='send_login_email'),
url(r'^login$', views.login, name='login'),
url(r'^login$', views.login, name='login'),
url(r'^logout$', logout, {'next_page': '/'}, name='logout'),
]
\ No newline at end of file
......@@ -45,4 +45,14 @@ class LoginTest(FunctionalTest):
lambda: self.browser.find_element_by_link_text('Log out')
)
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertIn(TEST_EMAIL, navbar.text) """
\ No newline at end of file
self.assertIn(TEST_EMAIL, navbar.text)
# Now she logs out
self.browser.find_element_by_link_text('Log out').click()
# She is logged out
self.wait_for(
lambda: self.browser.find_element_by_name('email')
)
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertNotIn(TEST_EMAIL, navbar.text) """
\ No newline at end of file
......@@ -14,15 +14,24 @@
<body>
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<a class="navbar-brand" href="/">Superlists</a>
<form class="navbar-form navbar-right" method="POST" action="{% url 'send_login_email' %}">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<a class="navbar-brand" href="/">Superlists</a>
{% if user.email %}
<ul class="nav navbar-nav navbar-right">
<li class="navbar-text">Logged in as {{ user.email }}</li>
<li><a href="{% url 'logout' %}">Log out</a></li>
</ul>
{% else %}
<form class="navbar-form navbar-right"
method="POST"
action="{% url 'send_login_email' %}">
<span>Enter email to log in:</span>
<input class="form-control" name="email" type="text" />
{% csrf_token %}
</form>
</div>
</form>
{% endif %}
</div>
</nav>
{% if messages %}
......
......@@ -32,7 +32,7 @@ DEBUG = True
ALLOWED_HOSTS = ['*']
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'ilhamperuzzi'
EMAIL_HOST_USER = 'ilhamperuzzi@gmail.com'
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
......
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