Fakultas Ilmu Komputer UI

README.md 6.54 KB
Newer Older
RANI LASMA ULI's avatar
RANI LASMA ULI committed
1
2
# 1606885025-practice

RANI LASMA ULI's avatar
RANI LASMA ULI committed
3
*Rani Lasma Uli - 1606885025 - Computer Science 2016 - PMPL A - Practice Repo*
Rani Lasma Uli's avatar
Rani Lasma Uli committed
4

RANI LASMA ULI's avatar
RANI LASMA ULI committed
5
6
## Outline
 - [Cerita Exercise 3](#cerita-exercise-3)
RANI LASMA ULI's avatar
RANI LASMA ULI committed
7
 - [Cerita Exercise 4](#cerita-exercise-4)
Rani Lasma Uli's avatar
Rani Lasma Uli committed
8
9
 - [Refactoring and Clean Code](#refactoring-and-clean-code)
 - [Why Need Test Organization](#why-need-test-organization)
RANI LASMA ULI's avatar
RANI LASMA ULI committed
10
11
12
13
 - [URL](#url)
 - [Install Modules](#install-modules)

### URL
Rani Lasma Uli's avatar
Rani Lasma Uli committed
14
http://pmpl-ranisianipar.herokuapp.com
Rani Lasma Uli's avatar
Rani Lasma Uli committed
15

RANI LASMA ULI's avatar
RANI LASMA ULI committed
16
### Install Modules
Rani Lasma Uli's avatar
Rani Lasma Uli committed
17
18
19
20
21
22
23
24
25
- activate the virtual environment
Windows: \env\Scripts\activate.bat

- install the requirements
pip install -r requirements.txt

- update module to requirements.txt
pip freeze > requirements.txt

RANI LASMA ULI's avatar
RANI LASMA ULI committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

### Cerita Exercise 3
This section contains exercise 3 details which refer to the obeythetestinggoat chapter 6.

#### Steps I've been through
1. Refactoring <br>
sebelum mengimplementasikan `test isolation` dilakukan pemindahan file functional_tests.py ke dalam folder functional_tests dan mengubah nama file menjadi tests.py (functional_tests/tests.py). Django membutuhkan __init__.py untuk menjadi Python package yang valid, sehingga perlu ditambahkan file functional_tests/__init__.py. Hal ini berguna untuk pemanggilan functional_tests yang lebih mudah menjadi --> `python manage.py test functional_tests`

2. Using Python Test runner <br>
Untuk menggunakan Python Test runner class yang digunakan pada functional_tests/tests.py diubah dari UnitTest menjadi LiveServerTestCase. Untuk kode tes yang lebih baik, URL tidak perlu lagi menggunakan *hard code* untuk `localhost:8000`. LiveServerTestCase menyediakan atribut bawaan untuk URL app yang akan diuji, yaitu method *live_server_url*. Atribut tersebut akan dipanggil menjadi `self.live_server_url`.

3. Explicit to Implicit waiting <br>
Pada chapter 5, functional_tests.py menunggu selama 1 detik untuk output data. Namun pada chapter 6 ini, data akan dipanggil sampai hasilnya diperoleh. Waktu tunggu maksimal adalah 10 detik. Kode yang kali ini lebih efektif karena waktu tunggu untuk hasil lebih dinamis (menyesuaikan lama waktu elemen diperoleh).

*Where's the Test Isolation implemented?* <br>
Test Isolation sendiri adalah mengisolasi setiap tes untuk menghilangkan ketergantungannya satu sama lain antar tes. Pada awalnya kita menjalankan functional_tests.py memengaruhi database `item` yang ada. Hal ini tidak baik karena akan mengganggu nilai yang akan diuji oleh tes yang lain. Untuk mempersiapkan database setiap test method dapat menggunakan `setUp` dan `tearDown` method. Selain dari cara itu, untuk Django 1.4++ disediakan class LiveServerTestCase yang secara otomatis menyediakan test database.

#### Before 'n After

1. `localhost:8000` or any hard code URL (staging URL) --> self.live_server_url <br>
- Before
```python
self.browser.get('localhost:8000' + TO_DO_LIST_PATH)
```

- After
```python
self.browser.get(self.live_server_url + TO_DO_LIST_PATH)
```
2. Add a helper method which will be responsible for the `implicit waiting`, also define maximum time as the waiting time limit <br>
solution: add wait_for_row_in_list_table method
- After
```python
# GLOBAL VARIABLE IN THIS CLASS
MAX_WAIT = 10
    def wait_for_row_in_list_table(self, row_text):
        start_time = time.time()
        while True:  
            try:
                table = self.browser.find_element_by_id('id_list_table') 
                rows = table.find_elements_by_tag_name('tr')
                self.assertIn(row_text, [row.text for row in rows])
                return  
            except (AssertionError, WebDriverException) as e:  
                if time.time() - start_time > MAX_WAIT:  
                    raise e
                time.sleep(0.5)  
```
3. Call the helper method <br>
- Before
```python
def test_can_start_a_list_and_retrieve_it_later(self):
    ...
    time.sleep(1)
    ...
    ...
    self.check_for_row_in_list_table('1: Buy peacock feathers')
    self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')
    ...
```
- After
```python
def test_can_start_a_list_and_retrieve_it_later(self):
    ...
    self.wait_for_row_in_list_table('1: Buy peacock feathers')
    ...
    ...
    # The page updates again, and now shows both items on her list
    self.wait_for_row_in_list_table('2: Use peacock feathers to make a fly')
    self.wait_for_row_in_list_table('1: Buy peacock feathers')
RANI LASMA ULI's avatar
RANI LASMA ULI committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
```

### Cerita Exercise 4
Pada latihan kali ini, saya melakukan functional test untuk styling. Secara singkat, kegiatan latihan ini mengetes posisi elemen yang berada di tengah.

Untuk tes fungsional yang melibatkan lebar dan tinggi window, kita perlu mengatur ukuran window.

```python
def test_layout_and_styling(self):
        # goes to the homepage
        self.browser.get(self.live_server_url)
        self.browser.set_window_size(1024, 768)
```

Selanjutnya, kita membuat tes untuk memastikan elemen berada di tengah dalam method yang sama.

```python
        # the input box centered
        inputbox = self.browser.find_element_by_id('id_new_item')
        self.assertAlmostEqual(inputbox.location['x'] + inputbox.size['width'] / 2, 512, delta=10)
```
Tes pun akan gagal, maka kita perlu mengimplementasikan styling pada layout.
Pada konteks ini, posisi elemen dapat dibuat menjadi di tengah dengan menambahkan "text-align=center" secara in-line. 

```html
<p style="text-align:center">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
</p>

...
```

Sehingga tes pun `PASSED`. Cara serupa dapat dilakukan pada elemen lainnya. Prinsip yang dilakukan tetap menggunakan metode TDD. Untuk pengembangan software yang lebih baik lagi, kegiatan styling secara in-line patut dihindari. Hal ini dapat dilakukan dengan melakukan refactoring, yaitu memindahkan styling ke dalam satu file (css,sass). 
Refactoring dapat dilakukan dengan menambahkan...
```html
<link href="/static/.../css/{nama_file}.css" rel="stylesheet">
```
dan memindahkan semua styling ke dalam file tersebut.

Rani Lasma Uli's avatar
Rani Lasma Uli committed
135
136
### Refactoring and Clean Code

RANI LASMA ULI's avatar
RANI LASMA ULI committed
137

138
139
### Why Need Test Organization
Test Organization menjadi penting saat test yang dibuat akan banyak. Jika semua test ditaruh dalam 1 file, debugging akan sulit. File test menjadi sangat panjang dan readability-nya berkurang. Untuk menghindari kondisi semacam ini, kita perlu mengorganisir sejumlah test ke dalam file (class) terpisah untuk memastikan helper method pada test menjadi reusable, menghindari redundant code, dan meningkatkan readability code. Readability code sangatlah penting untuk perkembangan aplikasi yang lebih besar, seperti penambahan fitur atau perubahan requirement yang biasa terjadi pada penerapan Agile Methodology. Jadi, kesadaran untuk menjaga readability code harus disadari sedari awal pengembangan.