วันพฤหัสบดีที่ 29 มกราคม พ.ศ. 2558

Test-Driven Development with Python - สรุป Chapter. 1-4

คำสำคัญที่พูดถึงในหนังสือ TDD with Python

Test-Driven Development (TDD) 

Test-Driven Development (TDD) คือรูปแบบการพัฒนา app โดยการเริ่มจากการสร้างตัว test ก่อน แล้วจึงเขียนโค้ดของโปรแกรม เปรียบได้กับการวาง spec ของโปรแกรมที่เราต้องการก่อนจึงค่อยสร้างโปรแกรมตาม spec ที่เราวางไว้ ช่วยให้สามารถสร้างโปรแกรมได้ตามความต้องการ การสร้างตัว test ย่อยๆของแต่ละส่วนสามารถทำให้รู้ตำแหน่งที่เกิด bug ได้โดยไม่ต้องไล่โค้ดทั้งหมด อีกทั้งยังสามารถลอง test โค้ดในขณะกำลังสร้างได้เรื่อยๆ

แหล่งที่มาเพิ่มเติม :
http://www.siamhtml.com/test-driven-development-introduction/

Functional Test vs Unit Test

Functional Test คือการทดสอบในมุมมองของ user เป็นการมอง app ที่เราทดสอบจากด้านนอกเปรียบเสมือน "black box" โดยไม่สนใจว่ามีการทำงานอย่างไรอยู่ภายใน สนใจเพียงว่า output ที่ได้นั้นมีการทำงานที่ถูกต้องตรงตามความต้องการหรือไม่

Unit Test คือการทดสอบในมุมมองของ programmer คือการมอง app โดยสนใจที่ตัวโค้ด เป็นการ test ที่ช่วยในแก้ bug ในการเขียนโค้ด ตรวจสอบว่าโค้ดที่เราเขียนนั้น error ตรงไหน อย่างไร ช่วยให้สามารถเขียนโค้ดได้ถูกต้อง ไม่มี bug

Refactoring

Refactoring คือ การกลับมาปรับปรุงโค้ดที่เคยเขียนไปแล้วและทำงานได้อย่างถูกต้องแล้ว ให้สั้นลง กระชับมากขึ้น ทำงานได้เร็วมากขึ้น อ่านได้ง่ายมากขึ้น ลดความซับซ้อนของโค้ด

แหล่งที่มาเพิ่มเติม :
http://meewebfree.com/site/php-codeigniter/432-what-is-refactoring-code
http://refactoring.com/

สรุปการทดลองใช้งานคำสั่งตามหนังสือ TDD with Python

Functional Test
  • การสร้าง Project ของ Django สำหรับเก็บ web app ของเรา
1. สร้างไฟล์ functional_tests.py สำหรับเป็นตัวทดสอบ functional test ซึ่งตัว Functional Test เราจะใช้ library ของ Selenium ในการเขียน
2. สร้างที่สำหรับเก็บโปรเจคด้วยคำสั่ง
django-admin.py startproject superlists
 จะสร้างโฟล์เดอร์ชื่อ superlists และมีไฟล์ย่อยๆดังนี้
.
├── functional_tests.py
└── superlists
    ├── manage.py
    └── superlists
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py
 3. ย้ายไฟล์ functional_tests.py เข้าไปอยู่ในโฟล์เดอร์ superlists อันนอกโดยคำสั่ง
mv functional_tests.py superlists/

  • การรัน Development Server ของ Django 
การทดสอบ functional test จะเป็นที่จะต้องสร้าง Server ขึ้นมาสำหรับรัน functional test โดยใช้คำสั่ง
python3 manage.py runserver
จะได้ Server บน IP 127.0.0.1 port 8000

  • การรัน Functional Test นั้นต้องรันบน Server ข้างต้นซึ่งรันโดยใช้คำสั่ง
python3 functional_tests.py

Git Repository
Git Repository คือ library หนึ่งที่สำหรับใช้จัดการ version control system (VCS) ซึ่งจะผูกมัดกับไฟล์และบันทึกแต่ละ version ของไฟล์งานเราไว้ หากเราเขียนโค้ดแล้วเกิดบัคเราก็สามารถเรียกเวอร์ชั่นก่อนหน้าเพื่อที่จะเรียกกลับมาดูหรือเขียนใหม่ต่อจากเวอร์ชั่นก่อนหน้าที่จะบัคได้

แหล่งที่มาเพิ่มเติม :
http://git-scm.com/book/th/v1
http://www.narisa.com/forums/index.php?app=blog&blogid=9&showentry=2814

การสร้าง Git Repository ใหม่เราจะเข้าไปในโฟลเดอร์ superlists แล้วใช้คำสั่ง
git init .
จะสร้าง Repository เปล่าๆขึ้นมาให้เรา


เราสามารถเพิ่มส่วนที่เหลือก็คือไฟล์งานต่างๆของที่อยู่ใน superlists ซึ่งเป็น current folder ของเราในตอนนี้โดยการใช้คำสั่ง
git add .
 โดยที่ "." หมายถึง current folder


การเรียกดูการเปลี่ยนแปลงของ Git Repository ใช้คำสั่ง
git status
ซึ่งจะแสดงว่าไฟล์ที่เราผูกมัด (commit) ไว้กับ git อันไหนมีการแก้ไขบ้าง ไฟล์ไหนที่เราพึ่งทำการผูกมัด ไฟล์ไหนที่ git ติดตาม (tracked)และไฟล์ไหนที่เราไม่ได้ให้ git ติดตาม (untracked)


การยืนยันไฟล์ที่มาจาก git add ให้เข้าไปใน Git Repository ใช้คำสั่ง
git commit
ซึ่งจะเก็บไฟล์ที่ add เข้ามาใหม่และบันทึกการแก้ไขไฟล์ไว้เป็นเวอร์ชั่นใหม่และมีการเปิดหน้า nano ให้เขียน comment ไว้เพื่อให้เรารู้ว่าตอนนี้โปรแกรมที่เราเขียนนั้นสำเร็จไปถึงไหนแล้ว เวลาเรียกกลับมาดูจะได้หาได้ง่าย


git diff
เป็นคำสั่งที่จะแสดงการแก้ไขไฟล์ที่เราผูกมัดไว้อย่างละเอียด ว่ามีการเพิ่มเข้าลบออกอย่างไร


git commit -a
-a คือจะบันทึกการเปลี่ยนแปลงทั้งหมดของไฟล์ที่เรา commit ไว้และเปลี่ยนไฟล์เป็นไฟล์ที่ git จะติดตาม (tracked) อัตโนมัติ

git commit -m "<comment>"
-m คือเราสารมารถเขียน comment ต่อท้ายคำสั่งได้เลยโดยไม่ต้องเข้าไปแก้ในหน้า nano

git log --oneline
จะแสดงเวอร์ชั่นและ comment ต่างๆที่เราได้บันทึกไว้



Unit Test
การเขียน Unit Test หากจะใช้ library ของ python นั่นสามารถเขียนในไฟล์ functional_tests.py ได้เลยโดย import unittest

หรือหาจะใช้ unit test ของ Django ก็ใช้ได้ง่าย เนื่องจาก Django จะสร้างไฟล์สำหรับทดสอบ unit test ให้อัตโนมันติเมื่อเราสร้าง app โดยมีขั้นตอนดังนี้

  • การเริ่มสร้าง app สำหรับ project ใช้คำสั่ง
python3 manage.py startapp lists
 ตามหนังสือนั้นเราจะสร้าง app สำหรับบันทึกรายการสิ่งที่เราจะต้องทำ จึงใช้ชื่อ app ว่า lists โดยที่แต่ละโปรเจคนั้นสามารถมีได้มากกว่า 1 app เมื่อสร้าง app แล้วจะมีการสร้างโฟล์เดอร์ชื่อ lists
superlists/
├── db.sqlite3
├── functional_tests.py
├── lists
│   ├── admin.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── superlists
    ├── __init__.py
    ├── __pycache__
    ├── settings.py
    ├── urls.py
    └── wsgi.py

  • การเขียน unit test นั้นตามที่บอกข้างต้นคือ Django จะสร้างไฟล์สำหรับการ test ให้เราอัตโนมัติเมื่อเราสร้าง app ซึ่งเป็นไฟล์ชื่อว่า lists/tests.py
from django.core.urlresolvers import resolve
from django.test import TestCase
from lists.views import home_page 

class HomePageTest(TestCase):

    def test_root_url_resolves_to_home_page_view(self):
        found = resolve('/')  
        self.assertEqual(found.func, home_page) 

จากตัวอย่างเป็นการฟังก์ชั่น resolve จะทำการแก้ไข '/' ให้เป็นมุมมองแบบ url ก็คือเป็น root ของหน้าเว็บ (home page) แล้วฟังก์ชั่น assertEqual จะตรวจสอบว่าหน้าที่ import มาจากไฟล์ lists.views นั้นเป็นหน้า home page จริงๆหรือไม่




from django.core.urlresolvers import resolve
from django.test import TestCase
from django.http import HttpRequest

from lists.views import home_page


class HomePageTest(TestCase):

    def test_root_url_resolves_to_home_page_view(self):
        found = resolve('/')
        self.assertEqual(found.func, home_page)


    def test_home_page_returns_correct_html(self):
        request = HttpRequest()  
        response = home_page(request)
        self.assertTrue(response.content.startswith(b'<html>'))
        self.assertIn(b'<title>To-Do lists</title>', response.content)
        self.assertTrue(response.content.endswith(b'</html>'))

จากตัวอย่างมีการ test ว่าในโค้ด html ของตัว home page นั้นต้องขึ้นต้นด้วย <html> มี <title>To-Do lists</title> อยู่ในช่วงกลางๆของโค้ด html และปิดท้ายโค้ดด้วย </html>
และตามหนังสือให้แก้ในไฟล์ lists/views.py ซึ่งเป็นไฟล์ที่ lists.tests.py จะเรียกใช้ฟังก์ชัน home_page โดยในที่นี้จะให้ลอง return เป็นโค้ด html ตามที่ test.py ต้องการ
from django.http import HttpResponse
    def home_page(request):
        return HttpResponse('<html><title>To-Do lists</title></html>')


Refactoring to Use a Template

Django สามารถสร้าง template สำหรับหน้าเว็บได้ โดยจะต้องสร้าง folder ที่ lists/templates ตามข้อตกลงของ Django และลองสร้าง file lists/templates/home.html เพื่อลองเขียนเป็นโค้ด html จริงๆ (ตอนแรกเราให้ตัว view.py return โค้ด html ไปเลยเพื่อทดสอบตัว test ก่อน เป็นการ Refactoring โปรแกรมให้มีการทำงานสมจริงยิ่งขึ้น) โดยไปแก้ให้ view.py มาอ่านโค้ด html จากไฟล์ home.html จริงๆดังนี้
from django.shortcuts import render

def home_page(request):
    return render(request, 'home.html')

แต่เนื่องจาก lists เป็น app ที่เราสร้างขึ้นมา แต่ทาง Django ไม่ได้หาให้เราอัตโนมัติเราจำเป็นจะต้องบอก Django เพิ่มเติมในไฟล์ superlists/settings.py ว่าเรามี app ชื่อ lists โดยเพิ่มคำว่า 'lists', ในฟังก์ชั่นดังนี้
# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'lists',
)
จากนั้นก็จะเป็นการเพิ่มส่วนของโค้ด html ให้มี spec ตามที่ตัว Functional test ต้องการ

อ้างอิงจากหนังสือ Test-Driven Development with Python by Harry Percival :
http://chimera.labs.oreilly.com/books/1234000000754

วันพฤหัสบดีที่ 22 มกราคม พ.ศ. 2558

HTML แสดงตารางจากการประมวลผลไฟล์ .csv

โค้ดภาษา Python

วิธีการรันโปรแกรม
1. นำไฟล์ที่ต้องการจะประมวลผลไปไว้ที่ directory /home/pongsarkorn/Desktop/rawdata

2. เข้าไปใน directory ที่ไฟล์โค้ดภาษา Python อยู่ ด้วยคำสั่ง cd
3. รันโปรแกรมด้วยคำสั่ง python

4. จะแสดงโค้ด HTML สำหรับ render บน Server ขึ้นมา

และจะมีไฟล์เอาต์พุตเป็น .csv ออกมาที่ directory /home/pongsarkorn/Desktop

สามารถเปิดด้วยโปรแกรม Spreadsheet ได้

5. จะทำการ render ด้วย CGI HTTP Server จะต้องตั้งค่าให้ไฟล์ สามารถทำการ execution ได้

6. ใช้คำสั่ง ls ตรวจสอบว่าสามารถทำการ execution ได้ (ชื่อจะเป็นสีเขียว)
7. จำลอง CGI HTTP Server ด้วยคำสั่ง python -m CGIHTTPServer

8. เข้าไปยัง browser เพื่อเปิดไฟล์ภาษา Python สามารถ render ได้

แหล่งข้อมูล
ฟังก์ชัน remove_values_from_list สำหรับลบข้อมูลออกจากลิสท์
http://stackoverflow.com/questions/1157106/remove-all-occurences-of-a-value-from-a-python-list
ฟังก์ชัน split()
http://www.tutorialspoint.com/python/string_split.htm
คำสั่ง encode HTML ให้สามารถรันเป็นภาษาไทยได้
http://www.w3.org/International/O-charset.th.php
คำสั่งเขียนจาก list ออกไปยังไฟล์ .csv
http://stackoverflow.com/questions/14037540/writing-a-python-list-of-lists-to-a-csv-file


วันจันทร์ที่ 19 มกราคม พ.ศ. 2558

การจำลอง CGI HTTP Server เพื่อ Render จากโค้ดภาษา Python เป็น HTML

โค้ด Python ที่จะ Render เป็นโค้ด HTML


โค้ด HTML ในส่วนของตาราง
 

การตั้งค่าให้ Server สามารถ Execute ไฟล์ได้
วิธีการ
1. เมื่อเขียนโค้ดภาษา Python เสร็จ ให้บันทึกเป็นนามสกุล .py หรืออะไรก็ได้ ใน Directory ชื่อว่า cgi-bin ทำการคลิ๊กขวา เลือก Properties

2. ทำเครื่องหมายถูกตรงช่อง Allow executing file as program

3. ตรวจสอบว่าไพล์ดังกล่าวสามารถ Execute ได้ โดยการใช้คำสั่ง cd ตามด้วย Directory ที่ไฟล์อยู่ (cgi-bin/) 
4. ใช้คำสั่ง ls เพื่อเรียกดูว่ามน Directory มีไฟล์อะไรบ้าง หากไฟล์สามารถ Execute ได้จะเป็นสีเขียว


จำลอง CGI HTTP Server
วิธีการ
1. เข้าไปใน Directory ที่ไฟล์ HTML อยู่
2. ใช้คำสั่ง python -m CGIHTTPServer เพื่อจำลอง CGI HTTP Server จะขึ้นบอกว่าแสดงเซิฟเวอร์ที่ 0.0.0.0 พอร์ต 8000
 
3. เมื่อเปิด Web Browser ไปตามที่อยู่จะแสดง Directory และ File ที่มีอยู่ใน Directory ที่เราอยู่ตอนสร้างเซิฟเวอร์
 
4. เมื่อกดเข้าไปใน Directory แล้วจะขึ้น Error Response จะต้องพิมพ์ชื่อไฟล์โค้ด Python ต่อใน url เอง


5. จะแสดงหน้าเว็บที่ได้จากการ Render โค้ด Python

การเขียนไฟล์.html ด้วยโค้ด Python และการจำลอง Simple HTTP Server

โค้ด Python 

โค้ด HTML

รันโค้ดภาษา Python เพื่อสร้างไฟล์ HTML
วิธีการ
1. ใช้คำสั่ง cd เข้าไปยัง directory ที่ไฟล์โค้ด Python อยู่
2. ใช้คำสั่ง python เว้นวรรคตามด้วยชื่อไฟล์ เพื่อเป็นการรันไฟล์
3. ตามโปรแกรมของโค้ดจะให้ใส่ชื่อเพื่อไปแสดงบนเว็บที่จะสร้าง

ไฟล์ HTML ที่ได้จากการรันโค้ด


การจำลอง Simple HTTP Server
วิธีการ
1. เข้าไปใน Directory ที่ไฟล์ HTML อยู่
2. ใช้คำสั่ง python -m SimpleHTTPServer เพื่อจำลอง Simple HTTP Server จะขึ้นบอกว่าแสดงเซิฟเวอร์ที่ 0.0.0.0 พอร์ต 8000

3. เมื่อเปิด Web Browser ไปตามที่อยู่จะแสดง Directory และ File ที่มีอยู่ใน Directory ที่เราอยู่ตอนสร้างเซิฟเวอร์

4. เมื่อกดเข้าไปยังไฟล์ .html ที่เป็นผลลัพธ์จากการรันโค้ด Python แล้ว จะแสดงหน้าเว็บจากโค้ด html นั้นขึ้นมา