Fakultas Ilmu Komputer UI

Commit fa59f1d4 authored by RANI LASMA ULI's avatar RANI LASMA ULI
Browse files

Merge branch 'testinggoat/ex9' into 'master'

Testinggoat/ex9

See merge request !11
parents 59021c39 76cd0619
Pipeline #26352 passed with stages
in 3 minutes and 26 seconds
...@@ -31,27 +31,18 @@ Deployment: ...@@ -31,27 +31,18 @@ Deployment:
url: $HEROKU_APP_HOST url: $HEROKU_APP_HOST
FunctionalTest: FunctionalTest:
image: python:3.7 image: joyzoursky/python-chromedriver
stage: functionalTest stage: test
before_script: before_script:
- wget -qO- https://cli-assets.heroku.com/install-ubuntu.sh | sh - pip install -r requirements.txt
- export HEROKU_API_KEY=$HEROKU_APIKEY - python3 manage.py migrate
- heroku pg:reset DATABASE --app $HEROKU_NAME --confirm $HEROKU_NAME || true - python3 manage.py compilescss
- heroku restart --app $HEROKU_NAME || true - python3 manage.py collectstatic --no-input
- heroku run --app $HEROKU_NAME migrate || true
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
- echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list
- apt-get update -qq && apt-get install -y -qq unzip
- apt-get install -y google-chrome-stable
- apt-get install -y xvfb
- wget https://chromedriver.storage.googleapis.com/77.0.3865.40/chromedriver_linux64.zip - wget https://chromedriver.storage.googleapis.com/77.0.3865.40/chromedriver_linux64.zip
- unzip chromedriver_linux64.zip - unzip chromedriver_linux64.zip
- pip install -r requirements.txt
when: on_success when: on_success
allow_failure: true allow_failure: true
script: script:
- python3 manage.py test functional_tests - python3 manage.py test functional_tests
after_script:
- heroku pg:reset DATABASE --app $HEROKU_NAME --confirm $HEROKU_NAME || true
- heroku run --app $HEROKU_NAME migrate || true
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
- [Why Need Test Organization](#why-need-test-organization) - [Why Need Test Organization](#why-need-test-organization)
- [Mutation Testing](#mutation-testing) - [Mutation Testing](#mutation-testing)
- [Mocking Manually vs Library](#mocking-manually-vs-library) - [Mocking Manually vs Library](#mocking-manually-vs-library)
- [Ch 20 vs Ch 18](#test-fixture-and-decorator)
- [URL](#url) - [URL](#url)
- [Install Modules](#install-modules) - [Install Modules](#install-modules)
...@@ -309,4 +310,14 @@ Also, using library for mocking is pretty simple - in this case just using @patc ...@@ -309,4 +310,14 @@ Also, using library for mocking is pretty simple - in this case just using @patc
> >
> Mocking with Library: > Mocking with Library:
> 1. Readable code, no object creation in testing class > 1. Readable code, no object creation in testing class
> 2. Fully-package! No need to write the construct the object (fake) to mock real object > 2. Fully-package! No need to write the constructor of the object (fake) to mock real object
#### Test Fixture and Decorator
Perbedaan antara Ch 20 vs Ch 18:
- Pada chapter 20, saya menggunakan method `create-pre-authenticated` yang berfungsi untuk membuat session. Session adalah cara browser untuk mengenali request HTTP yang dimana memiliki sifat stateless.
- Adanya penambahan `@wait` yang bertingkah laku sebagai decorator. Kode pada file `base.py` memiliki sejumlah pemanggilan fungsi `self.wait_for...` dimana pada fungsi-fungsi tersebut menggunakan fungsi `wait_for`. Melihat hal ini, refactor dapat dilakukan dengan membuat 1 fungsi bernama `wait`. Khusus untuk latihan kali ini, fungsi `wait` dibuat agar dapat diakses sebagai decorator (menerima fungsi sebagai parameter).
> Mengapa kode pada ch 20 lebih baik dari kode ch 18?
- Refactor sebuag fungsi yang sering dipakai menjadi fungsi yang dapat diakses sebagai decorator membuat kode menjadi lebih readable dan ringkas.
- Penggunaan session pada authentication itu adalah sebuah keharusan untuk HTTP dengan sifatnya yang stateless. FungsionalTest kali ini menjadi lebih sesuai dengan rekayasa penggunaan browser. Di tambah lagi, dengan adanya session kita dapat melayani user secara spesifik dan data pribadi (yang tidak terlalu penting namun sangat memungkinkan untuk dipakai berkali-kali) dapat disimpan pada session.
\ No newline at end of file
...@@ -10,6 +10,21 @@ from unittest import skip ...@@ -10,6 +10,21 @@ from unittest import skip
MAX_WAIT = 10 MAX_WAIT = 10
def wait(fn):
def modified_fn(*args, **kwargs):
start_time = time.time()
while True:
try:
return fn(*args, **kwargs)
except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT:
raise e
time.sleep(0.5)
return modified_fn
class FunctionalTest(StaticLiveServerTestCase): class FunctionalTest(StaticLiveServerTestCase):
def setUp(self): def setUp(self):
self.BASE_URL = os.environ.get("HEROKU_HOST", self.live_server_url) self.BASE_URL = os.environ.get("HEROKU_HOST", self.live_server_url)
...@@ -36,6 +51,7 @@ class FunctionalTest(StaticLiveServerTestCase): ...@@ -36,6 +51,7 @@ class FunctionalTest(StaticLiveServerTestCase):
def tearDown(self): def tearDown(self):
self.browser.quit() self.browser.quit()
@wait
def wait_for_row_in_list_table(self, row_text): def wait_for_row_in_list_table(self, row_text):
start_time = time.time() start_time = time.time()
while True: while True:
...@@ -49,6 +65,7 @@ class FunctionalTest(StaticLiveServerTestCase): ...@@ -49,6 +65,7 @@ class FunctionalTest(StaticLiveServerTestCase):
raise e raise e
time.sleep(0.5) time.sleep(0.5)
@wait
def wait_for(self, fn): def wait_for(self, fn):
start_time = time.time() start_time = time.time()
while True: while True:
...@@ -57,4 +74,17 @@ class FunctionalTest(StaticLiveServerTestCase): ...@@ -57,4 +74,17 @@ class FunctionalTest(StaticLiveServerTestCase):
except (AssertionError, WebDriverException) as e: except (AssertionError, WebDriverException) as e:
if time.time() - start_time > MAX_WAIT: if time.time() - start_time > MAX_WAIT:
raise e raise e
time.sleep(0.5) time.sleep(0.5)
\ No newline at end of file
@wait
def wait_to_be_logged_in(self, email):
self.browser.find_element_by_link_text('Log out')
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertIn(email, navbar.text)
@wait
def wait_to_be_logged_out(self, email):
self.browser.find_element_by_name('email')
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertNotIn(email, navbar.text)
...@@ -42,15 +42,10 @@ class LoginTest(FunctionalTest): ...@@ -42,15 +42,10 @@ class LoginTest(FunctionalTest):
self.browser.get(url) self.browser.get(url)
# she is logged in! # she is logged in!
self.wait_for( self.wait_to_be_logged_in(email=TEST_EMAIL)
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)
# Now she logs out # Now she logs out
self.browser.find_element_by_link_text('Log out').click() self.browser.find_element_by_link_text('Log out').click()
# She is logged out # She is logged out
self.wait_for(lambda: self.browser.find_element_by_name('email')) self.wait_to_be_logged_out(email=TEST_EMAIL)
navbar = self.browser.find_element_by_css_selector('.navbar')
self.assertNotIn(TEST_EMAIL, navbar.text)
from django.conf import settings
from django.contrib.auth import BACKEND_SESSION_KEY, SESSION_KEY, get_user_model
from django.contrib.sessions.backends.db import SessionStore
from .base import FunctionalTest
User = get_user_model()
class MyListsTest(FunctionalTest):
def create_pre_authenticated_session(self, email):
user = User.objects.create(email=email)
session = SessionStore()
session[SESSION_KEY] = user.pk
session[BACKEND_SESSION_KEY] = settings.AUTHENTICATION_BACKENDS[0]
session.save()
## to set a cookie we need to first visit the domain.
## 404 pages load the quickest!
self.browser.get(self.live_server_url + "/404_no_such_url/")
self.browser.add_cookie(dict(
name=settings.SESSION_COOKIE_NAME,
value=session.session_key,
path='/',
))
def test_logged_in_users_lists_are_saved_as_my_lists(self):
email = 'edith@example.com'
self.browser.get(self.BASE_URL)
self.wait_to_be_logged_out(email)
# Edith is a logged-in user
self.create_pre_authenticated_session(email)
self.browser.get(self.BASE_URL)
self.wait_to_be_logged_in(email)
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