2011年9月11日 星期日

Ruby on Rails 的整合測試 (Integration testing)

撰寫自動化測試是寫程式非常重要的一環,在 Ruby 裡有許多的測試框架,但最多人推崇的非 RSpec 莫屬。

關於 RSpec 的介紹,可以參考:

 

但若要完成整合測試,光靠 RSpec 可能還是有點不足,這時我們可以配合 Capybara 做更完整的測試。

Capybara 會偷開 Server (rails server),然後讓測試程式真的訪問我們所寫的 Web,因此所得到的互動結果是真實發生的狀況。

這個網站有非常清楚關於 RSpecCapybara 的教學

http://opinionated-programmer.com/2011/02/capybara-and-selenium-with-rspec-and-rails-3/

 

實際寫起來可以像這樣

#encoding: utf-8
require 'spec_helper'
 
describe '活動頁面' do
  it '第一次進入此頁面,應該跳轉至註冊頁面' do
    visit '/campaigns'
    page.current_url.should =~ %r(http://[^/]+/sign_up)
  end
  
  it '實際註冊後,應該跳轉至登入頁面' do
    visit '/sign_up'
    fill_in 'user_email', :with => 'root@example.com'
    fill_in 'user_password', :with => 'root'
    fill_in 'user_password_confirmation', :with => 'root'
    click_on '註冊'
    
    page.current_url.should =~ %r(http://[^/]+/log_in)
  end
end

 

看了上面的例子,像不像在寫 spec 一樣呀?其實這個 spec 是可以拿來測試的喔!

 

其它

如果需要指定測試 Server 開啟在指定 port 的話,可以下達以下指令

Capybara.server_port = 3000

要回到 random port 的話,那麼可以…

Capybara.server_port = nil

 

2011/9/28 更新

記得把測試資料夾設定成 ./spec/requests/*_spec.rb,或是在每個測試項目加上「:type => :request」。如果資料夾不這麼命名,那就不會默認有「:type => :request」這個設置…成立一個新專案,要建置測試時出錯,找了一天才找到解法…

it 'xxxxxxxxxxxxx', :type => :request do
    # ......
end

 

參考資料

https://github.com/jnicklas/capybara/issues/483

2011年9月10日 星期六

Ruby on Rails multipart(上傳檔案) 讓 remote(ajax) 失效!

在 RoR 要 AJAX 來傳遞表單(form)非常的簡單,只需要把 form 的 remote 屬性設定成 true 就好。

<%= form_tag('/posts', :remote => true) %>
  # field here ...
<% end %>

 

而關於 AJAX event 的 handle,可以參考這篇

Rails 3 Remote Links and Forms: A Definitive Guide

 

 

但若要傳遞的是檔案就沒這麼簡單了,因為 form 的 multipart 屬性會讓 remote 失效!

<%= form_tag('/posts', :remote => true, :multipart => true) %>
  # field here ...
<% end %>

 

這並不是  RoR 的問題,而是 Javascript 本來就無法存取本機得資源,若要達成還是得利用 iframe 來讓瀏覽器幫忙將檔案送到 server 端而不重新讀取頁面,以 php 為例,你必須這樣做。

index.php

<form id="upload_form" method="post" enctype="multipart/form-data" action="upload.php">
    <input name="file" id="file" type="file"/>
    <input type="submit" name="action" value="Upload"/>
    <iframe id="upload_iframe" name="upload_iframe" style="width: 500px; height: 500px; border: 1px solid #000;"></iframe>
</form>
 
<script>
function init() {
    document.getElementById('upload_form').onsubmit=function() {
        document.getElementById('upload_form').target = 'upload_iframe';
    }
}
window.onload=init;
</script>

 

upload.php

<pre>
<?
    // 處理一般 upload 的程式碼放這,這邊只印出 $_FILES 的內容
    print_r($_FILES);
?>
</pre>
 
<script>
// 還是可以呼叫到前一個頁面的元素進行互動
alert(parent.document.getElementById('upload_form'));
</script>

 

在 RoR 世界裡,已經有人把他寫成套件了,或許安裝有點繁瑣,使用起來也不是那麼的順手,但基本上還是維持了 RoR 的一致性,可以參考看看底下這個 solution。(裡面已有安裝教學以及使用範例)

https://github.com/leppert/remotipart

2011年9月7日 星期三

Facebook API 循序圖

image
(圖的來源在 http://developers.facebook.com/docs/authentication/)

圖裡指的 APP 為 Facebook 中的 APP,通常以 WebSite 方式存在,以下皆以 WebSite 稱之。

步驟解說如下:

  1. 使用者來到 WebSite
  2. WebSite 提供一個連結至 Facebook 的「請求授權」頁面,連結的參數裡,帶有 WebSite 指定成功後跳轉的網址(通常指回自己身上),「請求授權」頁面會自動偵測使用者登入狀況來決定是否跳轉登入頁面。
  3. 「請求授權」成功後,Facebook 會通知 Browser 跳轉到步驟 2 指定的網址,並帶有 "code" 的參數。(這邊的 "code" 指的是「請求授權」成功的密鑰)
  4. WebSite 收到 "code" 之後,透過 "code" 連接到 Facebook 表示使用者已同意 WebSite 取得「access token」
  5. 取得「access token」之後,WebSite 便可透過「access token」直接對 Facebook 下達任何使用者授權的存取動作。

能請求的授權如下:
(來源在 http://developers.facebook.com/docs/reference/api/permissions/)

image
image
image
image

2011年9月6日 星期二

Ruby on Rails and Facebook API (koala)

 

我很訝異我無法在第一時間就 google 到 RoR 整合 Facebook API 的 solution。雖然不到千辛萬苦,但也是兜了一圈才找到這個 koala 套件。

https://github.com/arsduo/koala/wiki

 

如果要直接下載專案範例,那麼可以試試看

https://github.com/omeryavuz/yemek_koala

 

不知道是不是使用 VirtualBox 的關係,get_access_token 這個指令每次都回應我 auth_code 與 App id 不 match…但如果第二次訪問就可以正常取得 access_token,目前暫時用這個方式來解,還是得找時間實測看看實體機器。

2011年9月4日 星期日

Ruby on Rails 實戰聖經

image

 

連結如下:

Ruby on Rails 實戰聖經

 

看了這個網站一天,實在很佩服這位作者,讓我這個資質駑鈍的人可以很快的進入狀況,幾乎把每一個步驟有可能遇到的狀況與問題都描述的非常清楚。一般來說,高手常常會有盲點,他根本不知道新手究竟會遭遇到什麼問題,只能順順的帶過,但這作者真的非常巨細靡遺的講解,一定要好好推薦一下這位作者,以及即將出版的書!

2011年9月3日 星期六

Desktop Application Get Facebook access_token via Browser (on windows)

 

前言

如果應用程式是以 Web 為 base,那麼要能取得 Facebook 的 access_token 是比較容易的。這篇主要是讓非 Web Application 的開發者取得 access_token 的紀錄。

 

這篇適合稍微碰過 Facebook API 的人,若你對 Facebook API 並不熟,那麼閱讀這篇之前,你可以先試著閱讀...

 

 

facebook 官方也提到他們的 OAuth 2.0 認證機制並不直接支援一般的應用程式。

https://developers.facebook.com/docs/authentication/

image

 

可參考底下網站,有更詳細的解說
http://blog.ericsk.org/archives/1422

 

雖不直接支援,但 https://developers.facebook.com/docs/authentication/ 仍有提供解法,但前提是你的應用程式必須能呼叫 Browser。

在 Windows 上,只要透過 win32 api,其實要辦到這件事情並不困難,以下用 Ruby 做為範例語言:

程式碼

GetAccess_Token.rb

require 'win32ole'
 
# Enter Your app_id & app_secret
app_id = ''
app_secret = ''
 
ie = WIN32OLE.new('InternetExplorer.Application')
 
ie.Visible = true
ie.Navigate('http://www.facebook.com/dialog/oauth?
                client_id=' + app_id + '&
                redirect_uri=http://www.facebook.com/connect/login_success.html&
                scope=publish_stream,read_stream,read_friendlists,user_likes,friends_likes,offline_access')
 
sleep(2) until ie.ReadyState == 4
loop do
    break if ie.document.body.innertext.strip() == "Success"
end
 
code = ie.LocationURL.sub('http://www.facebook.com/connect/login_success.html?code=', '')
 
ie.Navigate('https://graph.facebook.com/oauth/access_token?
            client_id=' + app_id + '&
            client_secret=' + app_secret + '&
            redirect_uri=http://www.facebook.com/connect/login_success.html&
            code=' + code)
 
sleep(2) until ie.ReadyState == 4
 
dummy, access_token = ie.document.body.innertext.strip().split('=')
puts 'access_token : '
puts access_token
ie.Quit

 

其實只是利用 win32 api 開啟瀏覽器連結到 Facebook 提供的網址,而使用者照著操作之後,再利用 win32 api 取得瀏覽器中的資料而已。

操作畫面像這樣,

 

執行程式

image

 

跳出瀏覽器要求使用者登入

image

 

授權請求

image

 

接著你的程式就得到 access_token 啦!(在這邊我只是印出來而已)

image

Github 與 Git GUI (For Windows)

SNAGHTML3fa20a

雖然我並不排斥 command line 的操作,但某些情況 command line 的確是比較不順手,對我來說最重要的是如何快速的使用滑鼠進行操作,稍微研究了一下,原來 Git on Windows 工具本來就有提供這個 feature。(雖然很陽春,但開發一個專案下來,大部分的操作也脫離不了這些個功能)

 

首先還是得依底下的網址按表操課:

http://help.github.com/win-set-up-git/

 

其中有一個步驟會安裝 Git on Windows

image 

 

接著試著利用 Git on Windows 不下任何 command line 開發一個新專案。

建立一個空資料夾

SNAGHTML523401

 

在空白的地方按右鍵,並點選紅框的 Git Init Here

SNAGHTML52d87f

 

會產生 .git 資料夾,在建立一個新檔案(檔名隨便,這例子中用的是 README)

image

 

在空白的地方按右鍵,並點選藍框的 Git Add all files now

SNAGHTML56e9d1

 

如此一來這個專案就認得這個資料夾下所有的檔案了(現在只有 README)

此時編輯檔案 README 並存檔。

SNAGHTML5a9322

 

在空白的地方按右鍵,並點選藍框的 Git Commit Tool

SNAGHTML5b62c6

 

螢光紫的部份是我填寫的 commit 訊息,按下紅框內的 Commit,這樣就完成了第一次的 Commit

SNAGHTML5dbcd3

 

如果再有變動,那麼也是在空白的地方按右鍵,並點選藍框的 Git Commit Tool,此時畫面會變這樣

SNAGHTML601673

 

第二次(含以上)變動與第一次變動比較不一樣的地方是,你必須去點選此次欲 Commit的檔案(紅色箭頭),或是點選橘色箭頭所指的 Stage Changed 按鈕選擇所有有更動過的檔案。

SNAGHTML623924

 

之後欲 Commit 的檔案便會跑到下面的欄位,此時便與之前 Commit 的方式相同了。

SNAGHTML654b75

 

也可以在空白的地方按右鍵,並點選藍框的 Git History 觀看 Commit Log

SNAGHTML69fb1a

SNAGHTML6ab5a0

 

先介紹到這,其實還有很多 GUI for Git(有空再來玩玩看!)

http://kylecordes.com/2010/git-gui-client-windows