วันศุกร์ที่ 15 เมษายน พ.ศ. 2559

Deploy Web App to Heroku "Part 1" เตรียมความพร้อม

Deploy Web App to Heroku "เตรียมความพร้อม"

    ในการทดสอบในครั้งนี้ ผมได้ทำการทดสอบ Deploy web app ที่ได้ออกเเบบไว้ลงบน Web Heroku เเละใช้ Python กับ Django Framework version 1.9.2 ในการออกเเบบ web app ใช้ os ubuntu 15.10 64Bit น่ะครับ  

  • ขั้นเเรกให้ทำการสมัคใช้งานเว็บ Heroku ก่อนครับ 

    Heroku คือผู้ให้บริการ Platform as a Services (PaaS) เช่น แอพพลิเคชันเซิร์ฟเวอร์, ดาต้าเบสเซิร์ฟเวอร์ หรือมิดเดิลแวร์อื่นๆ ไม่ต้องเสียเวลาหา software ไม่ต้องหา server และลดความยุ่งยากในการ configuration เพราะเพียงแค่คลิกเลือกภาษาที่ต้องการสร้าง app ไม่ถึงนาทีเราก็มี environment พร้อมใช้งาน ที่สำคัญฟรีครับ สามารถสมัคใช้งานได้ที่ www.heroku.com

  • ทำการติดตั้งเครื่องมือต่างๆดั้งนี้ครับ

        1. Virtualenv ช่วยในการแยก environment ในการทำงาน Python ของแต่ละโปรเจคออกจากกัน เพราะเวลาเราทำงานหลายๆโปรเจค แต่ละโปรเจคอาจจะต้องการใช้ Python library version ต่างๆกัน การลงทุก version ในเครื่องจะทำให้ library ตีกันได้ง่าย เราจึงนิยมใช้ virtualenv ในการแยก environment การทำงานออกจากกัน

     $ sudo pip install virtualenv  

        2. Postgres เป็น DBMS เป็นระบบจัดการฐานข้อมูลแบบ object-relational database management system หรือ (ORDBMS) พัฒนาที่ University of California, Berkeley (มหาวิทยาลัย) เริ่มโครงการโดย Michael Stonebraker เมื่อปี พ.ศ. 2528 ในยุคแรกชื่อของระบบเรียกว่า post-Ingres เนื่องมาจากจากเป็นระบบที่มีวิวัฒนาการมาจากระบบจัดการฐานข้อมูล Ingres
    คุณสมบัติสำคัญของ PostgreSQL คือการมีคุณสมบัติ ACID ((Atomicity, Consistency, Isolation, Durability) ครบถ้วนโดยสนับสนุน foreign keys, joins, views, triggers, และ stored procedures (หลายภาษา) โดยมีชนิดข้อมูลใน SQL92 และ SQL99 ได้แก่ INTEGER, NUMERIC, BOOLEAN, CHAR, VARCHAR, DATE, INTERVAL, และ TIMESTAMP
    นอกจากนี้ PostgreSQL ยังทำงานในหลายแพลทฟอร์มได้แก่ Linux, UNIX (AIX, BSD, HP-UX, SGI IRIX, Mac OS X, Solaris, Tru64), และ Windows
    ลักษณะสำคัญอีกอย่างหนึ่งคือ PostgreSQL เป็นซอฟต์แวร์แบบรหัสเปิดใช้ลิขสิทธิ์ BSD ซึ่งหมายถึงผู้ใช้สามารถนำไปใช้งานได้ฟรี นอกจากนี้ในปัจจุบัน PostgreSQL ไม่อยู่ภายใต้การควบคุมขององค์กรใดโดยเฉพาะแต่มีผู้ร่วมพัฒนาจากทั่วโลกทำให้ PostgreSQL มีการปรับปรุงอย่างต่อเนื่อง

     $ sudo apt-get install postgresql postgresql-contrib

    จากนั้น ให้ทำการสร้าง user account Postgres

     $ sudo -u postgres createuser --superuser $USER
     $ sudo -u postgres createdb $USER

    จากนั้น ให้สร้างไฟล์ history ไว้เก็บประวัติ โดยย้อนกลับมาที่หน้า home ด้วยคำสั่ง cd จากนั้นใช้คำสั่ง

     $ touch .psql_history

    ถ้าสำเร็จถูกต้องเมื่อพิม psql ต้องแสดงแบบนี้ ถึงจะใช้ได้ เวลาออกให้พิม \q 

        3. install heroku toolbelt สำหรับ ubuntu (โปรแกรมหลักของ heroku เอาไว้จัดการกับcodeที่จะเอาขึ้น heroku)

     $ wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh

      เท่านี้เราก็พร้อมเเล้วล่ะครับ !!

วันพุธที่ 10 กุมภาพันธ์ พ.ศ. 2559

Test-Driven Development with Python - Chapter. 4

What Are We Doing with All These Tests?

      - ทำการแก้ไขไฟล์ functional_tests.py

 
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest

class NewVisitorTest(unittest.TestCase):

    def setUp(self):
        self.browser = webdriver.Firefox()
        self.browser.implicitly_wait(3)

    def tearDown(self):
        self.browser.quit()

    def test_can_start_a_list_and_retrieve_it_later(self):
        # Edith has heard about a cool new online to-do app. She goes
        # to check out its homepage
        self.browser.get('http://localhost:8000')

        # She notices the page title and header mention to-do lists
        self.assertIn('To-Do', self.browser.title)
        header_text = self.browser.find_element_by_tag_name('h1').text
        self.assertIn('To-Do', header_text)

        # She is invited to enter a to-do item straight away
        inputbox = self.browser.find_element_by_id('id_new_item')
        self.assertEqual(
                inputbox.get_attribute('placeholder'),
                'Enter a to-do item'
        )

        # She types "Buy peacock feathers" into a text box (Edith's hobby
        # is tying fly-fishing lures)
        inputbox.send_keys('Buy peacock feathers')

        # When she hits enter, the page updates, and now the page lists
        # "1: Buy peacock feathers" as an item in a to-do list table
        inputbox.send_keys(Keys.ENTER)

        table = self.browser.find_element_by_id('id_list_table')
        rows = table.find_elements_by_tag_name('tr')
        self.assertTrue(
            any(row.text == '1: Buy peacock feathers' for row in rows)
        )

        # There is still a text box inviting her to add another item. She
        # enters "Use peacock feathers to make a fly" (Edith is very
        # methodical)
        self.fail('Finish the test!')

        # The page updates again, and now shows both items on her list

if __name__ == '__main__':  
    unittest.main()  
 
ภาพ(ผลการrun functional_tests.py)

      - ใช้คำสั่ง git commit

 
$ git diff # should show changes to functional_tests.py  
$ git commit -am "Functional test now checks we can input a to-do item"
        
 ภาพ(ผลการใช้คำสั่ง git commit)   

  
  • The “Don’t Test Constants” Rule, and Templates to the Rescue

      - ทำการทดสอบ list/tests.py 

 
$ python manage.py test
        

ภาพ(ผลการทดสอบไฟล์ test.py)  

      - ทำการสร้างสร้างโฟล์เดอร์ใหม่ชื่อ templates ใน list และสร้างไฟล์ home.html และทำการแก้ไขไฟล์ list/templates/home.html ดังนี้ 
 
<html>
    <title>To-Do lists</title>
</html>
        
       - ทำการแก้ไขไฟล์ lists/views.py เพื่อจะใช้ทำการ render ไฟล์ home.html ขึ้นเป็นหน้า page html      
 
from django.shortcuts import render

def home_page(request):
    return render(request, 'home.html')
        
           - ทดสอบไฟล์ test

 ภาพ(ผลการทดสอบไฟล์ test.py) 

       - แก้ไขไฟล์ superlists/settings.py โดยการเพิ่ม list เข้าไป
 
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'lists',
)
        
           - ทำการทดสอบไฟล์ test  จะพบว่ามี Error เนื่องจากต้องมี </html>  
    ภาพ(ผลการทดสอบไฟล์ test.py)
        - แก้ไขไฟล์ lists/tests.py
 
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>')) 
        self.assertTrue(response.content.strip().endswith(b'</html>')) 
        
        - ทำการทดสอบไฟล์ test จะพบว่าการทำงานผ่านแล้ว 
 ภาพ(ผลการทดสอบไฟล์ test.py)

        - แก้ไขไฟล์ lists/tests.py เพื่อเป็นการเรียกใช้ไฟล์ templates
    ใน Django จะมีฟังก์ชั่น render_to_string ให้เรียกใช้ เพื่อให้บันทึกผลเป็น String
 
from django.template.loader import render_to_string
[...]

    def test_home_page_returns_correct_html(self):
        request = HttpRequest()
        response = home_page(request)
        expected_html = render_to_string('home.html')
        self.assertEqual(response.content.decode(), expected_html)
        
  • On Refactoring 
- ใช้คำสั่ง git status เพื่อดูสถานะไฟล์
- ใช้คำสั่ง git commit เพื่อ commit ว่า "Refactor home page view to use a template"
 
 $ git status # see tests.py, views.py, settings.py, + new templates folder  
 $ git add . # will also add the untracked templates folder  
 $ git diff --staged # review the changes we're about to commit  
 $ git commit -m"Refactor home page view to use a template"  
        



 ภาพ(ผลการใช่คำสั่งดังกล่าว)
  • A Little More of Our Front Page  
        - แก้ไขไฟล์ lists/templates/home.html
 
<html>
    <head>
        <title>To-Do lists</title>
    </head>
    <body>
        <h1>Your To-Do list</h1>
    </body>
</html>
        
             - ทำการทดสอบไฟล์ functional_tests.py  จะปรากฎหน้าต่าง browser ขึ้นมาและโปรแกรมจะแสดงผล Error ดังนี้ 
 
 $ python functional_tests.py
        
ภาพ(ผลการrun functional_tests.py)
 ภาพ(ผลการrun functional_tests.py) 

          - แก้ไขไฟล์ lists/templates/home.html
 
<html>
 <head>
  <title>To-Do lists</title>
 </head>
 <body>
  <h1>Your To-Do list</h1>
  <input id="id_new_item" />
 </body>
</html>
        
ภาพ(ผลการrun functional_tests.py) 

          - แก้ไขไฟล์ lists/templates/home.html
 
<html>
 <head>
  <title>To-Do lists</title>
 </head>
 <body>
  <h1>Your To-Do list</h1>
  <input id="id_new_item" placeholder="Enter a to-do item" />
 </body>
</html>
        
ภาพ(ผลการrun functional_tests.py)

 ภาพ(ผลการrun functional_tests.py)

          - แก้ไขไฟล์ lists/templates/home.html
 
<html>
 <head>
  <title>To-Do lists</title>
 </head>
 <body>
  <h1>Your To-Do list</h1>
  <input id="id_new_item" placeholder="Enter a to-do item" />
                <table id="id_list_table">
  </table>
 </body>
</html>
ภาพ(ผลการrun functional_tests.py)

          - ทำการ commit
 
 $ git diff
 $ git commit -am"Front page HTML now generated from a template"
           
ภาพ(ผลการ run $ git diff)


   - - - - - - - - - -