วันศุกร์ที่ 15 พฤษภาคม พ.ศ. 2558

Test3

Bitbucket : https://bitbucket.org/chananan/test3/commits/all 

ใน commit มีของtest2 เนื่องจาก นำงานของ test2 มาแก้ต่อ ทำให้มี commitของtest2 มาอยู๋ในงานนี้ด้วย

วันพฤหัสบดีที่ 7 พฤษภาคม พ.ศ. 2558

Assignment-2


Bitbucket :  https://bitbucket.org/panlapa_khemarungsarit/assingment-2
Pythonanywhere : http://galiblenight.pythonanywhere.com/

blog ของสมาชิก
1.bss56-20081.blogspot.com
2.bss56-30132.blogspot.com

comment Assignment-2 ของกลุ่มเพื่อน

กลุ่มที่1 https://bitbucket.org/cprekmutnbb2/assignment_ii/overview

-ยังมีะกดผิดบ้างบางคำเช่น เช็ค -> เชค

-use case เพิ่มภาพยนตร์และใส่รายละเอียดของข้อมูล มีการอธิบายรวมมากเกินไป ควรมีการแยกออกมาเป็นข้อๆ


กลุ่มที่2 https://bitbucket.org/assignment2_WTY/assignment2
 -ไม่มีครับ

assignment-1

https://bitbucket.org/chananan/a1

วันพฤหัสบดีที่ 9 เมษายน พ.ศ. 2558

ตรวจสอบรายชื่อ และขนาดไฟล์

การหาขนาดของไฟล์ ใน Directories ที่ต้องการ 
 

ทำการเปิด Server แบบ CGI โดยใช้คำสั่ง python -m CGIHTTPServer 
 
Code:
#!/usr/bin/python
print "Content-type: text/html\n\n"

import os

path = "/home/chananan/cgi-bin"

print "Path : %s <br>" % path
list_file = os.listdir(path)
for file in list_file:
 print "-"
 size = os.path.getsize(path+"/"+file)
 print file+": size ="
 print str(size)+"bytes<br>"


แสดงผล :
     code บรรทัดที่ 1 เนื่องจาก ทำการเปิด Server แบบ CGI  จึงกำหนด ไฟล์ให้เป็น python

     code บรรทัดที่ 2 เป็นการกำหนดให้เป็น HTML

     code บรรทัดที่ 3 เป็นการนำเข้าฟังก์ชัน

     code บรรทัดที่ 5 กำหนด path ที่เราต้องการจะดู

     code บรรทัดที่ 8-9 เป็นคำสั่งในการคนหารายชื่อไฟล์ ใน path

     code บรรทัดที่ 11 เป็นคำสั่งหาขนาดของไฟล์ข้อมูล

     code บรรทัดที่ 12-13 ให้แสดงชื่อไฟล์ + ขนาด
*คำสั่งเรียกดูขนาดของไฟล์ ไม่สามารถดูขนาดไฟล์ของ Folder ได้ ซึ่งจะแสดงเป็น 4096

Test2

Web application

โปรแกรมคำนวนเงินออม โดยใส่จำนวนเงินเข้าไป และจะมีการแสดง ผลรวม ค่าเฉลี่ย ค่าน้อยสุด ค่ามากสุด ในการออมเงินที่ผ่านมา



source code : https://bitbucket.org/chananan/test2

วันจันทร์ที่ 23 กุมภาพันธ์ พ.ศ. 2558

Test-Driven Development with Python Chapter 6

Getting to the Minimum Viable Site

Ensuring Test Isolation in Functional Tests

 เริ่มต้นตามหนังสืออธิบายว่าตอนนี้ database ที่เราใช้ในการ Functional Test นั้นเป็น database จริง ซึ่งมีการบันทึกข้อมูลจากตัว test ลงไปใน db.sqlite3 ซึ่งจริงๆแล้วตัว test ไม่ควรจะไปยุ่งกับข้อมูลใน database ที่เราใช้งาน โดยใน Django มี Class ชื่อว่า LiveServerTestCase ที่จะช่วยจำลอง database ขึ้นมาให้เรา
ซึ่ง LiveServerTestCase ใช้ตัวรัน Functional Test ของ Django ซึ่งต้องรันที่ manage.py และจะค้นหาไฟล์ที่ขึ้นต้นด้วย test ซึ่งเราจะทำการสร้าง directory สำหรับ FT โดยเฉพาะ และเปลี่ยนชื่อ file เป็น test.py

สร้าง directory ใช้คำสั่ง
mkdir functional_tests
และต้องสร้าง init file สำหรับ directory ของ python ที่จะใช้กับ Django ใช้คำสั่ง
touch functional_tests/__init__.py
ย้ายไปยัง directory functional_testและเปลี่ยนชื่อเป็น tests.py ใช้คำสั่ง

git mv functional_tests.py functional_tests/tests.py

At this point your directory tree should look like this:
.
├── db.sqlite3
├── functional_tests
│   ├── __init__.py
│   └── tests.py
├── lists
│   ├── admin.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── 0002_item_text.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   ├── models.py
│   ├── __pycache__
│   ├── templates
│   │   └── home.html
│   ├── tests.py
│   └── views.py
├── manage.py
└── superlists
    ├── __init__.py
    ├── __pycache__
    ├── settings.py
    ├── urls.py
    └── wsgi.py

แก้ไข Class ใน FT ให้รับ parameter จาก LiveServerTestCase

functional_tests/tests.py
 
from django.test import LiveServerTestCase 
     [....]
    class NewVisitorTest(LiveServerTestCase):
และเปลี่ยนจากการเรียก localhost port 8000 เป็นใช้ attribute ของ LiveServerTestCase
    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(self.live_server_url)
คำสั่งในการรัน FT ก็จะเปลี่ยนไป
python3 manage.py test functional_tests
 

และคำสั่งที่จะรัน Unit Test ก็ต้องเปลี่ยนด้วยเนื่องจากมี FT เพิ่มเข้ามา จึงต้องเจาะจงไปที่ test ใน lists

python3 manage.py test lists

Small Design When Necessary 

ต่อไปเราจะใช้แนวคิดของ REST ซึ่งจะใช้ URL structure ในการทำงานในกรณีต่างๆ ของ app lists ของเรา
  • โดยการระบุว่าจะเป็น list ไหน (รองรับหลาย list) ให้แต่ละ list มี URL เป็นของตัวเอง (ส่งการร้องขอไปยัง server แบบ GET Request คือการส่ง attribute ระบุข้อมูลที่ต้องการจาก server บนส่ง URL)
           /lists/<ชื่อ list>/
  • สร้าง list ใหม่ให้ส่งการร้องขอแบบ POST Request
           /lists/new
  • เพิ่มข้อมูลไปยัง list ที่มีอยู่แล้วทาง POST Request
           /lists/<ชื่อ list>/add_item
จากนั้นเราจะเพิ่มตัว FT ให้ตรวจสอบการใช้งานหลายๆ list
functional_tests/tests.py

    inputbox.send_keys('Buy peacock feathers')

    # When she hits enter, she is taken to a new URL,
    # and now the page lists "1: Buy peacock feathers" as an item in a
    # to-do list table
    inputbox.send_keys(Keys.ENTER)
    edith_list_url = self.browser.current_url
    self.assertRegex(edith_list_url, '/lists/.+') #1
    self.check_for_row_in_list_table('1: Buy peacock feathers')

    # There is still a text box inviting her to add another item. She
    [...]

 จากนั้นเราจะลองให้ FT สามารถใส่ข้อมูลได้หลายๆ list
    [...]
    # The page updates again, and now shows both items on her list
    self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')
    self.check_for_row_in_list_table('1: Buy peacock feathers')

    # Now a new user, Francis, comes along to the site.

    ## We use a new browser session to make sure that no information
    ## of Edith's is coming through from cookies etc #1
    self.browser.quit()
    self.browser = webdriver.Firefox()

    # Francis visits the home page.  There is no sign of Edith's
    # list
    self.browser.get(self.live_server_url)
    page_text = self.browser.find_element_by_tag_name('body').text
    self.assertNotIn('Buy peacock feathers', page_text)
    self.assertNotIn('make a fly', page_text)

    # Francis starts a new list by entering a new item. He
    # is less interesting than Edith...
    inputbox = self.browser.find_element_by_id('id_new_item')
    inputbox.send_keys('Buy milk')
    inputbox.send_keys(Keys.ENTER)

    # Francis gets his own unique URL
    francis_list_url = self.browser.current_url
    self.assertRegex(francis_list_url, '/lists/.+')
    self.assertNotEqual(francis_list_url, edith_list_url)

    # Again, there is no trace of Edith's list
    page_text = self.browser.find_element_by_tag_name('body').text
    self.assertNotIn('Buy peacock feathers', page_text)
    self.assertIn('Buy milk', page_text)

    # Satisfied, they both go back to sleep
เมื่อลองรัน FT แล้วจะ error

Iterating Towards the New Design

 สร้าง test ให้ redirect location หลังจากได้รับ POST
 lists/tests.py
self.assertEqual(response.status_code, 302)
self.assertEqual(response['location'], '/lists/the-only-list-in-the-world/')
 และแก้ใน lists/views.py
def home_page(request):
    if request.method == 'POST':
        Item.objects.create(text=request.POST['item_text'])
        return redirect('/lists/the-only-list-in-the-world/')

    items = Item.objects.all()
    return render(request, 'home.html', {'items': items})

ซึ่ง UT จะผ่านแต่ FT จะไม่ผ่าน
 จะ error ว่า เนื่องจากยังไม่มี list item ชื่อว่า the-only-list-in-the-world

Testing Views, Templates, and URLs Together with the Django Test Client

ต่อไปเราจะใช้ Django test client ช่วย Unit Test ในการตรวจสอบ การ map URL ,การตรวจสอบ views และการตรวจสอบการ render template ของ views โดยไปที่ lists/tests.py เพิ่มคลาสใหม่ ListViewTest หลังจากนั้น copy method ที่ชื่อว่า test_home_page_displays_all_ list_items จาก HomePageTest มาใส่ไว้ในคลาสใหม่แทน
  
lists/tests.py

class ListViewTest(TestCase):

    def test_displays_all_items(self):
        Item.objects.create(text='itemey 1')
        Item.objects.create(text='itemey 2')

        response = self.client.get('/lists/the-only-list-in-the-world/') #1

        self.assertContains(response, 'itemey 1') #2
        self.assertContains(response, 'itemey 2') #3




error เนื่องจากยังหา URL ไม่เจอ

A New URL
เราจึงไปสร้าง URL ใหม่ที่ superlists/urls.py 
urlpatterns = patterns('',
    url(r'^$', 'lists.views.home_page', name='home'),
    url(r'^lists/the-only-list-in-the-world/$', 'lists.views.view_list',
        name='view_list'
    ),
    # url(r'^admin/', include(admin.site.urls)),
)
รัน UT อีกครั้ง error ว่า import view_list ไม่ได้

AttributeError: 'module' object has no attribute 'view_list'
[...]
django.core.exceptions.ViewDoesNotExist: Could not import
lists.views.view_list. View does not exist in module lists.views.


ดังนั้นจึงไปสร้าง view_list ใน lists/views.py

def view_list(request):
    items = Item.objects.all()
    return render(request, 'home.html', {'items': items})
เมื่อรัน UT จะผ่านแต่รัน FT มี error
ต่อไปจะทำการ refactoring เอา test ที่ไม่จำเป็นแล้วออกจาก unit test
ดูว่าในไฟล์นั้นมี class และ function อะไรบ้างใช้คำสั่ง
 grep -E "class|def" lists/tests.py



เราจะลบ test_home_page_displays_all_list_items ออกเื่นองจากไ่มจำเ็ปนแ้ลว

A Separate Template for Viewing Lists  ยังทำไม่ได้

ต่อไปเราจะทำการแบ่ง template ของ home page กับ แสดง list ออกจากกัน
เริ่มต้นด้วยการสร้าง Unit Test ตรวจสอบว่าหน้าแสดง list ก็ใช้ template ของมันเอง
lists/tests.py
class ListViewTest(TestCase):

    def test_uses_list_template(self):
        response = self.client.get('/lists/the-only-list-in-the-world/')
        self.assertTemplateUsed(response, 'list.html')


    def test_displays_all_items(self):
        [...]
 และไปเปลี่ยนที่ views.py ให้เรียก list.html
lists/views.py
def view_list(request):
    items = Item.objects.all()
    return render(request, 'list.html', {'items': items})
เมื่อสร้าง test เสร็จจึงไปสร้าง template มา สร้างไฟล์ใหม่ใช้คำสั่ง
touch lists/templates/list.html
แล้วก็ copy เนื้อใน file มาจาก home.html ก่อน
cp lists/templates/home.html lists/templates/list.html
จากนั้นที่หน้า home เราจะเปลี่ยนคำที่แสดงบนหน้าแรกว่า start a new to-do list ให้สื่อความหมายว่าเป็นหน้าเริ่มต้น

lists/templates/home.html
<body>
    <h1>Start a new To-Do list</h1>
    <form method="POST">
        <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />
        {% csrf_token %}
    </form>
</body>
และไปแก้ที่ views.py ให้หลังจาก POST Request แล้วให้ redirect ไปหน้า list 

 lists/views.py
 def home_page(request):
    if request.method == 'POST':
        Item.objects.create(text=request.POST['item_text'])
        return redirect('/lists/the-only-list-in-the-world/')
    return render(request, 'home.html')


จากนั้นแก้ที่ list.html ให้มี action ไปยัง home_page (ไม่ให้กลับมาที่เดิมตาม default ของมัน)
lists/templates/list.html

   <form method="POST" action="/">  
ทดลองรัน FT
 

Another URL and View for Adding List Items


aยังทำไม่ได้