CSS

Showing posts with label Agile. Show all posts
Showing posts with label Agile. Show all posts

Watchr : simple continuous testing tool

Watchr is a pretty cool and simple tool for saving developer's time.

According to the preject description, watchr is:
Agile development tool that monitors a directory tree, and triggers a user defined action whenever an observed file is modified. Its most typical use is continuous testing, and as such it is a more flexible alternative to autotest.

But moreover, Watchr can be used on every simple task that need to execute a file, like markdown generate, coffee script compile, and the syntax is so simple to add those task in watchr script.

The syntax is like:

watch 'regular expression' { |matched_file| action_for matched_file }

#listen to all file and print filename when it modified
watch('.*') {|match| puts match[1]}

#listen to ruby file and run test
watch('lib/(.*)\.rb') {|match| system("ruby test/test_#{match[1]}.rb") }

#match[0] is full filename, match[1] is filename without extname.

running under command:
watchr script_name

Continous Testing


Continous Testing is a concept born from MIT Program Analysis Group,
It improve the Test Driven Development, which is auto run the corresponding test
in TDD right after the code saved. In this way, the test time lag will be reduced to zero,
and programer won't need to run the test to know the program is work or not. Makes testing become natural behavior in development.

Refers


ihower's rails3 watchr script template
Doc generate template from watchr project itself (dog fooding)

[Leader]領導者的六項特質

在別人的blog上看到的,轉自哈佛管理世界
留在這裡做個分享:

一:沉穩

(1)不要隨便顯露你的情緒。

(2)不要逢人就訴說你的困難和遭遇。

(3)在徵詢別人的意見之前,自己先思考,但不要先講。

(4)不要一有機會就嘮叨你的不滿。

(5)重要的決定儘量有別人商量,最好隔一天再發佈。

(6)講話不要有任何的慌張,走路也是。



二:細心

(1)對身邊發生的事情,常思考它們的因果關係。

(2)對做不到位的執行問題,要發掘它們的根本癥結。
(3)對習以為常的做事方法,要有改進或優化的建議。

(4)做什麼事情都要養成有條不紊和井然有序的習慣。

(5)經常去找幾個別人看不出來的毛病或弊端。

(6)自己要隨時隨地對有所不足的地方補位。



三:膽識

(1)不要常用缺乏自信的詞句

(2)不要常常反悔,輕易推翻已經決定的事。

(3)在眾人爭執不休時,不要沒有主見。

(4)整體氛圍低落時,你要樂觀、陽光!

(5)做任何事情都要用心,因為有人在看著你。

(6)事情不順的時候,歇口氣,重新尋找突破口,就結束也要乾淨俐落。



四:大度

(1)不要刻意把有可能是夥伴的人變成對手。

(2)對別人的小過失、小錯誤不要斤斤計較。

(3)在金錢上要大方,學習三施(財施、法施、無畏施)

(4)不要有權力的傲慢和知識的偏見。

(5)任何成果和成就都應和別人分享。

(6)必須有人犧牲或奉獻的時候,自己走在前面。



五:誠信

(1)做不到的事情不要說,說了就努力做到。

(2)虛的口號或標語不要常掛嘴上。

(3)針對客戶提出的"不誠信"問題,拿出改善的方法。

(4)停止一切"不道德"的手段。

(5)耍弄小聰明,要不得!

(6)計算一下產品或服務的誠信代價,那就是品牌成本。



六:擔當

(1)檢討任何過失的時候,先從自身或自己人開始反省。

(2)事項結束後,先審查過錯,再列述功勞。

(3)認錯從上級開始,表功從下級啟動。

(4)著手一個計畫,先將權責界定清楚,而且分配得當。

[Timeless way of Building] Pattern and Code Convention

Code Convention 是一連串Pattern的集合

Pattern是從許許多多解決問題的方法中,所找出來的,具有共通性的解法
Pattern是從context中誕生出來的,並由人命名而成為design pattern

Timeless way of building中,提到了好的建築中會有的Pattern
包括窗戶的大小,坐北朝南,房間的位址等等.
這些Pattern並沒有名稱,但是卻讓建築更為美好而偉大
我們稱為Quality Without A Name
而好的code也必須要有這些QWAN

1.一致性 : 大雜院 vs 社區

在code project中,我們時常會看到多種不同的寫法,
難以理解的命名與無法找到檔案的目錄架構
有統一的Convention可以讓檔案結構更容易理解
ex : 美國街道的street vs avenue,street為東西向,avenue為南北向,讓人一看就知道這條路往哪個方向
ex : 傳統的專案架構: doc,bin,obj,src...
ex : Pascal , _Camel等命名方式

2.更好的寫法Pattern與設計的指導原則

ex:使用多個if()來取代巢狀的if-else
ex:制定exception handle的規則
ex:遇到不知道的情況以簡單的方法優先
ex:使用String.isNullOrEmpty()來檢查空字串

3.讓犯錯變得困難
制定checkin policy : 於SourceControl設定code的檢查原則,要違反必須要設定attribute
使用using的關鍵字來管理連線,避免浪費連線資源
(Javascript)使用(function())()這種closure pattern來保持namespace的清潔

[Continuous Integration]使用CruiseControl.NET實現持續整合

Continuous Integration,CI,中文稱為持續整合
在Martin Flower的網站有著定義如下:
http://martinfowler.com/articles/continuousIntegration.html

Continuous Integration is a software development practice where members of a team integrate their work frequently,usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible.Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive
software more rapidly.

持續整合是一個軟體開發的實踐,讓開發團隊裡的每個成員頻繁的整合他們的工作,使每天都會有許多次的整合.
每次的整合都都由一台自動建置伺服器來驗證以及執行測試,來盡快的偵測到每次的整合錯誤.
許多團隊發現到這個方法能夠有效的減少整合的問題,並且讓團隊能夠更密切的合作並快速開發軟體.

JosephJ也有一篇很好的介紹文章:
http://www.josephj.com/entry.php?id=251

為什麼要持續整合呢?


每次有人commit code,功能作好了要佈署給使用者或Tester測試,
程式碼要執行測試與分析
要產生程式碼文件等等的時候
我們都是靠人工來執行整合的
每次都要把code checkout下來整合,執行一堆事情
更慘的是往往有人commit上了錯誤的程式碼,或漏掉一些元件
讓其他人update之後程式就不能跑了...然後花上時間去解決這些build problem
然後生命就浪費在這些無意義的事情上面

CI的意義就是利用srcipt的方式把這些工作整合起來
然後放在一個server上執行
只要有固定的script,這個整合步驟的執行頻率就可以提升到最多
可以每次有人commit就執行一次script,然後透過server,將產生的報告顯示在網頁上,或是以email的方式寄給大家,
最後自動將東西佈署到測試伺服器上
或是打包好可以使用,安裝

持續整合的例子 : Google Chrome 的Chromium BuildBot WaterFall
透過buildbot 執行多伺服器的Master-slave的持續整合架構
http://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/tour-of-the-chromium-buildbot

CruiseControl.NET


CruiseControl.NET是.NET平台一個open source的CI Server,
雖然在設定檔方面比較難以上手,需要用xml調整,
但是卻是適合沒錢和觀望的人嘗試CI的輕量級解決方案
Team City應該是比較好的選擇,只是要花錢
TFS則是很強大,和專案管理完全整合的重量級解決方案,不過要花錢
而且會與source control和其他MS的東西綁死

接下來會說明如何使用CCNET來持續整合一個簡單的專案 :
網路上也有很多說明文章:
http://omaralzabir.com/asp_net_website_continuous_integration_deployment_using_cruisecontrol_net__subversion__msbuild_and_robocopy/
這裡將會使用SVN,msbuild,mstest,msdeploy來作為持續建置的工具

1.安裝CCNet:


從SourceForge下載CCNET:http://sourceforge.net/projects/ccnet/ 並安裝

安裝好了之後在安裝目錄下(C:\Program Files\CruiseControl.NET\server)
會有ccnet.config檔案
這是設定所有持續整合工作的主要設定檔

於ccnet.config加入一個專案與工作:

    
        Hello CCNet
        
            
                c:\projects\Hello.cmd
            
        
    

建立c:\projects\Hello.cmd

echo 'Hello CCNet!!'

然後執行CCNet.exe開始整合
連到http://localhost/ccnet, 可以從DashBoard看到專案建置的狀況,
並可以點選forcebuild來執行工作,從buildlog看到執行訊息


2.設定ccnet.config

config檔的格式說明:http://confluence.public.thoughtworks.org/display/CCNET/Configuring+the+Server

設定專案:


    CITestProject
    c:\projects\CITestProject
    c:\projects\CITestProject\Log

workingDirectory:專案的所在目錄
artifactDirectory:儲存專案建置的Log目錄

之後所有的tag都是放在區塊內

設定Repository:


這裡使用的是SVN,現在也有對應git:

    https://@SVNHost/CITestProject/trunk/
    c:\projects\CITestProject
    BuildMaster
    ********
    36000000
    false
    Always

設定url,使用者名稱與密碼,要checkout的目錄等等,建置伺服器上要安裝svn
tips : 如果有裝Cygwin, commend line的svn 版本可能會是舊版,要先確認版本: svn --version
如果有憑證的話也要先手動接收一次,紀錄憑證訊息

設定trigger:


    

trigger是指在什麼時候執行整合,有分固定時間執行或定期檢查Source有沒有更改兩種Trigger
這裡設定了檢查頻率為60秒,如果發現SVN上有變更就會update並執行整合

設定build task:


    
    
        C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe
        C:\projects\CITestProject
        CITestProject.sln
        Clean;Build
        300
        C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll
        

artifactcleanup:清除專案建置的log

msbuild:
這裡使用visual studio的msbuild建置專案,msbuild的位置為
C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe
如使用.Net 4.0則要使用
C:\Windows\Microsoft.NET\Framework\v4.0\MSBuild.exe
並指定專案的.sln定義檔以執行建置

設定publishers: 如何以email或dashboard發佈專案結果


        
        
        
            
        
        
        
            
                Failed
                Fixed
            
        
        

        
            Failed
            Fixed
        

        
            xsl\header.xsl
            xsl\compile.xsl
            xsl\unittests.xsl
            xsl\modifications.xsl
        
    

email:設定寄信的host
users:設定接收email的使用者
groups:設定接受通知的群組與原則:這裡設定只有在build failed與fixed才會收到通知
modifierNotificationTypes: commit的人在什麼狀況下會收到的email訊息:設定為failed與fixed
xslFiles:email中的訊息會由buildlog + .xsl轉換而來,這裡設定email buildreport要包含的訊息

3.Test and Deploy

以下為我用到的其他整合tasks,放在標籤下
設定Test會讓每次的Build收到測試案例的檢核,如果有TestCase失敗,build也會定義為失敗
deploy則是放在最後一個task,讓每個通過testcase檢核的commit會即時deploy到伺服器上

Mstest:

        deleteTestResult.bat
        C:\projects\ESurvey
        
        300


        C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\mstest.exe
        C:\projects\ESurvey
        /testcontainer:CITestProject.Test\bin\Debug\CITestProject.Test.dll 
     /runconfig:LocalTestRun.testrunconfig 
     /resultsfile:testResults.trx
        300



    
       
           testResults.trx
       
    
    


deleteTestResult.bat:
del testResults.trx

mstest必須要在build server安裝Visual Studio才會有
要指定測試專案中的\bin\debug\@TestProjectName.dll 執行
第一個task是為了刪除mstest的記錄檔testResults.trx而執行的script,不然mstest會告訴你因為已經有了log檔而無法測試
一般mstest的記錄檔名稱是自動產生,但這裡因為要將檔案merge到buildReport所以要指定檔名
詳細說明 : http://blogs.blackmarble.co.uk/blogs/bm-bloggers/archive/2006/06/14/5255.aspx

RoboCopy & msdeploy:

在區域網路的其他機器進行WebApp的deploy時,可以使用robocopy與檔案分享來deploy:
 
    robocopy.exe
    C:\Windows\System32
    c:\projects\CITestProject\Web \\@DeployServerName\CITestProject /XD .svn /E /NDL /NC /NP /XO

或是使用msdeploy來佈署: http://www.iis.net/download/webdeploy

    msdeploy.exe
    C:\Program Files\IIS\Microsoft Web Deploy
    -verb:sync -source:contentPath="c:\projects\CITestProject\Web"
-dest:contentPath="C:\project\CITestProject\Web",computername=@DeployServerName,username=administrator,password=******* 
-skip:objectName=dirPath,absolutePath=.*\.svn
-skip:objectName=FilePath,absolutePath=.*\web.config


在確定整合工作沒有問題後,可以進入控制台=>服務 ,設定ccnet成為自動開啟的系統服務
於client端可以安裝CCTray,會於工作列新增一個小圖示,並隨時監控CI Server上的狀況

[Hollywood Principle] Dependency Injection Pattern

今天讀了Agile上面有關DIP的段落,乘機把它拿出來再複習一下:

首先,為什麼要用DIP呢?

書上舉了一個很好玩的例子來說明,叫"Hollywood Principle"
意思是"Don't Call me, I'll Call you"
好萊塢的經紀人不希望面試者主動聯絡他們,而是當他們決定要用你的時候才會主動聯絡。

以程式來說,就是讓物件自己決定要如何呼叫其他物件,而不是依賴於其他物件。

假設說今天我們要設計一個可以讀取Book資料的Reader

class Reader{
    private Book book = new Book("Harry Potter");
    public void read(int page){
        book.read(page);
    }
}

Reader依賴於book這個class的函式,
所以當我們要為這個程式增加可以閱讀EBook功能的時候,我們必須加入邏輯判斷來區別
第一個想到的就是新增TypeCode判斷,
於是醜陋的程式碼就產生了...

class Reader{
    static final int BOOK = 1,EBOOK = 2;
    public void read(int page, int bookType){
        if(bookType = BOOK){
            Book book = new Book("Harry Potter");
            book.read(page);
        }else if(bookType = EBOOK){
            EBook book = new EBook("Harry Potter");
            book.read(page);
        }
    }
}

使用Dependency Injection Pattern,能使Reader這個Class不會被book這個class綁死,
相反的,Reader可以先宣告自己會使用的介面,等於是告訴其他Class
"我會用這個方式來呼叫你,如果你想讓我用的話,就先實做這個介面":

class Reader{
    private IBook book;
    public void read(int page){
        book.read(page);
    }

    public Reader(IBook book){
        this.book = book;
    }
}

class Book implement IBook{...}
class EBook implement IBook{...}

使用介面,或是abstract class來宣告使用的介面,
讓Reader這個class可以不被單一的Book class所綁死
只要是實作IBook這個介面的Class,Reader都可以使用

public Reader(IBook book){
        this.book = book;
    }

而這段程式碼在呼叫Reader的建構式時傳入它要使用的Book
這就是Dependency Injection(控制反轉)的一種
是當你要使用物件的時候才傳入物件之間的依賴關係,而不是在一開始就在程式碼中指定
這樣可以保持物件之間彼此的鬆散偶合,增加擴充性.

另外,在作單元測試時,DI也是很有用的一個Pattern
如果我們要測試Reader的Read()這個函式,但是Read這個函式又會呼叫到Book,
然後Book會連接到背後的資料物件...這樣我們無法知道說測試的成功或失敗,
是因為Reader的關係,還是Book,或是背後的資料庫的問題.

這個時候我們就可以使用Dependency Injection的特性,將Book與Reader之間的關係給切開,
先寫一個測試用的Book,實作IBook的介面,並且紀錄是否被呼叫:

public class TestBook implement IBook(){
    public bool readed = false;
    public void read(int page){ 
        readed = true;
    }
}
//測試案例:
    public void ReaderTest(){

        TestBook book = new TestBook()   
        Reader reader = new Reader(book);
     
        reader.read();

        assertTrue(book.readed);
    }

利用這個方式,我們可以只測試我們想測試的邏輯.
也可以寫一個假的Data Access Class,將資料庫的部分先抽換掉,
來測試系統的介面與流程是否ok.

more:
Martin Flower提出的DI概念
良葛格對DI的詳細說明