<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>哇寶部落格 &#187; 軟體測試</title>
	<atom:link href="http://blog.wabow.com/archives/category/it/testing/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.wabow.com</link>
	<description>Wabow Information Inc. Blog</description>
	<lastBuildDate>Fri, 21 May 2010 15:11:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>PHPUnit 實務入門簡介</title>
		<link>http://blog.wabow.com/archives/2299</link>
		<comments>http://blog.wabow.com/archives/2299#comments</comments>
		<pubDate>Tue, 16 Mar 2010 13:28:53 +0000</pubDate>
		<dc:creator>jaceju</dc:creator>
				<category><![CDATA[技術分享]]></category>
		<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=2299</guid>
		<description><![CDATA[這幾天在寫折價券攤提到商品的數學演算法邏輯，搞得我七葷八素的...還好先前在製作購物車時，已經把單元測試放到架構裡，因此後面就只要專心應付演算法邏輯就好了。 雖然這樣的規劃聽起來不錯，但單元測試這件事說到底我的實務經驗還是太少，在這次的專案項目裡，才讓我真正有了較為深入的體會。 先對要測試的事情有一個概觀 其實測試一開始真的很難下手，主要是因為我們不知道我們要測些什麼東西。因此，我們需要對需要測試的東西有個概觀。 就以這次的例子來說吧，我要測試的東西就是「折價券攤提的演算法邏輯」，那它裡面重要的東西是什麼？ 在跟客戶討論，我們得知折價券面額要分攤到的商品上時有一定的規則；這時我們就要先在紙上作業，用簡單的例子跟客戶確認清楚規則。 確認了方向之後，因為我之前已經測試架構準備好了，所以接下來就只要針對要測試的部份撰寫程式碼即可。但如果一開始還沒有準備好測試架構的話，這裡給大家幾個建置環境的簡易流程： 在專案裡開個 tests 資料夾，這裡就是放置測試案例的地方。 準備一個 init.php ，目的是用來設置 include_path 及 autoload 機制。 按照 PHPUnit 官方的建議，建立一個 AllTests.php 的 Test Suite 。 註：這裡我就不列出程式碼了，讓大家自己試試看。 然後每次測試就用以下指令即可： &#62; phpunit AllTests.php 之後我會以「跑測試」來表示執行這個指令。 描繪程式的輪廓 接下來我們就要把整個系統的測試架構定義出來，不過這時候其實我們還沒開始寫程式，只是把流程和相關的方法先定義出來。 這裡的方法很簡單，就是先透過註解和方法介面來描述整個流程，而不是先寫細部的程式碼。 class Shop_Cart_Plugin_Coupon extends Shop_Cart_Plugin &#123; // ... 略 ... &#160; // 演算法計算後的結果 protected $_sharedCouponData = array&#40;&#41;; &#160; // 取得演算法計算後的結果，也可供測試來驗證 public functino [...]]]></description>
			<content:encoded><![CDATA[<p>這幾天在寫折價券攤提到商品的數學演算法邏輯，搞得我七葷八素的...還好先前在製作購物車時，已經把單元測試放到架構裡，因此後面就只要專心應付演算法邏輯就好了。</p>
<p>雖然這樣的規劃聽起來不錯，但單元測試這件事說到底我的實務經驗還是太少，在這次的專案項目裡，才讓我真正有了較為深入的體會。</p>
<p><span id="more-2299"></span></p>
<h2>先對要測試的事情有一個概觀</h2>
<p>其實測試一開始真的很難下手，主要是因為我們不知道我們要測些什麼東西。因此，我們需要對需要測試的東西有個概觀。</p>
<p>就以這次的例子來說吧，我要測試的東西就是「折價券攤提的演算法邏輯」，那它裡面重要的東西是什麼？</p>
<p>在跟客戶討論，我們得知折價券面額要分攤到的商品上時有一定的規則；這時我們就要先在紙上作業，用簡單的例子跟客戶確認清楚規則。</p>
<p class="image"><a href="http://www.jaceju.net/resources/phpunit/draft.jpg"><img src="http://www.jaceju.net/resources/phpunit/draft.jpg" alt="草圖" /></a></p>
<p>確認了方向之後，因為我之前已經測試架構準備好了，所以接下來就只要針對要測試的部份撰寫程式碼即可。但如果一開始還沒有準備好測試架構的話，這裡給大家幾個建置環境的簡易流程：</p>
<ol>
<li>
<p> 在專案裡開個 tests 資料夾，這裡就是放置測試案例的地方。</p>
</li>
<li>
<p> 準備一個 init.php ，目的是用來設置 include_path 及 autoload 機制。</p>
</li>
<li>
<p> 按照 PHPUnit 官方的建議，建立一個 AllTests.php 的 Test Suite 。</p>
</li>
</ol>
<p class="note">註：這裡我就不列出程式碼了，讓大家自己試試看。</p>
<p>然後每次測試就用以下指令即可：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">&gt; phpunit AllTests.php</pre></div></div>

<p>之後我會以「跑測試」來表示執行這個指令。</p>
<h2>描繪程式的輪廓</h2>
<p>接下來我們就要把整個系統的測試架構定義出來，不過這時候其實我們還沒開始寫程式，只是把流程和相關的方法先定義出來。</p>
<p>這裡的方法很簡單，就是先透過註解和方法介面來描述整個流程，而不是先寫細部的程式碼。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Shop_Cart_Plugin_Coupon <span style="color: #000000; font-weight: bold;">extends</span> Shop_Cart_Plugin
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 演算法計算後的結果</span>
    protected <span style="color: #000088;">$_sharedCouponData</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 取得演算法計算後的結果，也可供測試來驗證</span>
    <span style="color: #000000; font-weight: bold;">public</span> functino getSharedCouponData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> 
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_sharedCouponData<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// 主要的執行方法</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doCheckout<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getCouponData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 取得</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_getProductData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 取得商品資料</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_initData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 初始化要攤提的資料</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_shareCouponToProduct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 開始攤提</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>當然這些都是大概的輪廓，因為可能在我們寫好測試執行時，會再額外加入新的方法及介面。</p>
<p>還有一個要先定義好的是測試用的比對數據格式，它對我們稍後要測試的程式寫法會有影響。</p>
<h2>寫第一個測試</h2>
<p>到這裡，我們就可以開始寫第一個測試，而接下來的程式碼，都是先以這個測試可以成功為目的。而這個測試要怎麼寫呢？就是把一開始我們在紙上作業的數字拿進來套用。</p>
<p>當然這裡我的 setUp 和 tearDown 也已經在之前準備測試架構時寫好了，它們會讓我們每次的測試數據都能夠獨立。我們關心的就是第一個測試案例：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> Shop_Cart_Plugin_CouponTest <span style="color: #000000; font-weight: bold;">extends</span> PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testDoCheckout<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValue</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
           <span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// C1, ProductCoupon for P1, $100</span>
           <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// C2, ProductCoupon for P1, P2, $100</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cart<span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItems</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'P1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// $200</span>
            <span style="color: #0000ff;">'P2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// $300</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">refresh</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">300</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cart<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTotal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">doCheckout</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$resultDataList</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSelectedOrderCouponDataList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">100</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resultDataList</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'P1-C1'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'discountPrice'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$resultDataList</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'P1-C2'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'discountPrice'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">75</span><span style="color: #339933;">,</span>  <span style="color: #000088;">$resultDataList</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'P2-C2'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'discountPrice'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>這裡因為我們在上一步就定義好比對用的數據，所以測試時就是用這個輸出的數據來與我們預期的數字相比較。</p>
<p>接下來就先跑跑測試，看看這個 TestCase 有沒有執行錯誤的地方 (例如物件沒有正確初始化或是變數名稱誤寫等等) ；當然如果沒有出現預期值是正常的，因為我們根本還沒有寫計算公式。</p>
<h2>繼續完成演算法</h2>
<p>現在回到 Shop_Cart_Plugin_Coupon ，我們就要把剛剛那些只有骨頭的方法開始添血添肉，這裡就請大家自行發擇。</p>
<p>接著只要你覺得程式差不多了，就先跑一下測試，看看是不是符合測試的預期結果。</p>
<p>當你完成第一個測試時，程式的就差不多完成百分之五十啦，到這裡別忘了先把程式 commit 到版本控制系統裡。</p>
<h2>加入新測試並修改程式</h2>
<p>完成第一個測試時，當然不是沒事了，我們要針對不同的狀況再加入其他的測試數據。</p>
<p>這裡我們就可以開始考慮把第一個測試以 PHPUnit 提供的 Data Provider 改寫，讓我們不必重複過多的程式碼。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> Shop_Cart_Plugin_CouponTest <span style="color: #000000; font-weight: bold;">extends</span> PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @dataProvider provider
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testDoCheckout<span style="color: #009900;">&#40;</span><span style="color: #000088;">$selectedCouponIdList</span><span style="color: #339933;">,</span> <span style="color: #000088;">$productSkuNumberList</span><span style="color: #339933;">,</span> <span style="color: #000088;">$total</span><span style="color: #339933;">,</span> <span style="color: #000088;">$discountDataList</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValue</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$selectedCouponIdList</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cart<span style="color: #339933;">-&gt;</span><span style="color: #004000;">addItems</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$productSkuNumberList</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">refresh</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$total</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cart<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTotal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">doCheckout</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$resultDataList</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_plugin<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSharedCouponData</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$discountDataList</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        	<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$resultDataList</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'discountPrice'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> provider<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #666666; font-style: italic;">// 第一個測試</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// C1, ProductCoupon for P1, $100</span>
                <span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// C2, ProductCoupon for P1, P2, $100</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'P1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// $200</span>
                <span style="color: #0000ff;">'P2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// $300</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">300</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'P1-C1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">100</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'P1-C2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'P2-C2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">75</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #666666; font-style: italic;">// 第二個測試</span>
                <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #666666; font-style: italic;">// ... 略 ...</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>而加入新測試之後，就可以跑跑測試，看看我們剛寫好的演算法是否正確動作？通常這時候才真正是考驗的開始。因為這時候前面寫好的程式碼可能只對第一個測試正常，接下來的測試也許就會出錯了。</p>
<p>所以我們就會需要修改或重構程式碼，讓後面的測試也能正常執行。當然改過的程式也要讓第一個測試正常運作，才是正確的修改。</p>
<p>當然演算法寫好後，就要真正上到 Web 畫面去測試。至此，你會發現你花在寫測試上的心力都有了回報，因為通常如果你已經定義好介面，而這次的修改只是改寫一個小類別的話，那麼就會發現程式會非常順利地運作了。</p>
<h2>心得</h2>
<p>每次寫購物車時，最麻煩的就是測試時要開啟購物車網頁，把一個一個的商品加進來，再加入不同的折價券條件...</p>
<p>而有單元測試之後，我就可以省去一大堆開啟網頁，點選連結的功夫，專心地撰寫計算邏輯...只能說...單元測試真的個超級便利的工具呀。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/2299/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[PHP]免費的檔案瀏覽工具 fileNice</title>
		<link>http://blog.wabow.com/archives/2106</link>
		<comments>http://blog.wabow.com/archives/2106#comments</comments>
		<pubDate>Thu, 27 Aug 2009 07:34:03 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[技術分享]]></category>
		<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=2106</guid>
		<description><![CDATA[官方網站 http://filenice.com/ 展示網頁 http://filenice.com/demo/ 介紹 filenice是一套用php編寫的檔案瀏覽工具，作用在你本身如果有架設網站並有某個資料夾提供上傳檔案，當你想要查看這個資料夾中有哪些檔案時，filenice提供使用瀏覽器就可以查看的功能。 安裝 到官網下載檔案(http://filenice.com/demo/fileNice.zip)，下載完畢將解壓縮後的檔案放到網站伺服器上你想要瀏覽檔案的資料夾下即可。 優點 官方的說明是filenice是使用php+javascript也就是所謂的Ajax技術編寫的，因此速度比較快，而且當應用程式忙碌時可以返回而不會整個畫面當掉。此外使用filenice不需要安裝任何資料庫。 感想 filenice提供了無須安裝其他軟體，僅需使用瀏覽器就可觀看主機上提供upload的資料夾下的內容，也可自訂瀏覽檔案的一些排列等細節，另外也提供搜尋的功能。不過個人比較覺得可惜的是，因為無須登入帳密即可觀看，在安全性上稍顯不足，不過或是也因此除了觀看以外，並沒有額外提供刪除或是上傳的功能吧!?介紹給大家用看看!]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.wabow.com/wp-content/uploads/2009/08/sample10-500x260.gif" alt="sample10" width="500" height="260" class="aligncenter size-large wp-image-2107" /></p>
<p>官方網站  <a href="http://filenice.com/">http://filenice.com/</a><br />
展示網頁  <a href="http://filenice.com/demo/">http://filenice.com/demo/</a><span id="more-2106"></span></p>
<h3>介紹</h3>
<p>filenice是一套用php編寫的檔案瀏覽工具，作用在你本身如果有架設網站並有某個資料夾提供上傳檔案，當你想要查看這個資料夾中有哪些檔案時，filenice提供使用瀏覽器就可以查看的功能。</p>
<h3>安裝</h3>
<p>到官網下載檔案(http://filenice.com/demo/fileNice.zip)，下載完畢將解壓縮後的檔案放到網站伺服器上你想要瀏覽檔案的資料夾下即可。</p>
<h3>優點</h3>
<p>官方的說明是filenice是使用php+javascript也就是所謂的Ajax技術編寫的，因此速度比較快，而且當應用程式忙碌時可以返回而不會整個畫面當掉。此外使用filenice不需要安裝任何資料庫。</p>
<h3>感想</h3>
<p>filenice提供了無須安裝其他軟體，僅需使用瀏覽器就可觀看主機上提供upload的資料夾下的內容，也可自訂瀏覽檔案的一些排列等細節，另外也提供搜尋的功能。不過個人比較覺得可惜的是，因為無須登入帳密即可觀看，在安全性上稍顯不足，不過或是也因此除了觀看以外，並沒有額外提供刪除或是上傳的功能吧!?介紹給大家用看看!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/2106/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>用 PHP 查 DOMAIN 的 CNAME 紀錄</title>
		<link>http://blog.wabow.com/archives/2066</link>
		<comments>http://blog.wabow.com/archives/2066#comments</comments>
		<pubDate>Thu, 27 Aug 2009 06:44:34 +0000</pubDate>
		<dc:creator>suzy</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[cname]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=2066</guid>
		<description><![CDATA[接獲一項來自 Neo 的任務, "用PHP 實作由 CNAME 去判定新加入服務的 DOMAIN 為申請人所有" (證明他不是來亂的). For Example: Google Apps 就是用這個方式去作驗證 CNAME 是 DOMAIN or SUB DOMAIN 指向另一個 DOMAIN 的方式. (跟 alias 一樣) 那麼如果要用 PHP 實作呢? 有兩種方式 : 1. PHP5 內建的 dns_get_record() (Windows &#38; BSD &#38; Mac 不適用) 2. PEAR NET_DNS NET_DNS 原理是用 fsockopen("你的 DNS SERVER IP", 53), 但是要先自己組合出 "封包的header data" [...]]]></description>
			<content:encoded><![CDATA[<p>接獲一項來自 Neo 的任務, "用PHP 實作由 CNAME 去判定新加入服務的 DOMAIN 為申請人所有" (證明他不是來亂的).</p>
<p>For Example:<br />
<a href="http://www.google.com/support/a/bin/answer.py?hl=b5&amp;answer=92354">Google Apps 就是用這個方式去作驗證</a><br />
<span id="more-2066"></span></p>
<p><a href="http://www.google.com.tw/search?hl=zh-TW&amp;q=CNAME">CNAME</a> 是 DOMAIN or SUB DOMAIN 指向另一個 DOMAIN 的方式. (跟 alias 一樣)</p>
<p>那麼如果要用 PHP 實作呢? 有兩種方式 :<br />
1. PHP5 內建的 dns_get_record() (Windows &amp; BSD &amp; Mac 不適用)<br />
2. PEAR <a href="http://pear.php.net/package/Net_DNS">NET_DNS</a></p>
<p>NET_DNS 原理是用 fsockopen("你的 DNS SERVER IP", 53),<br />
但是要先自己組合出 "封包的header data" 再丟過去, DNS Server 才會理你唷.<br />
這些複雜的部份 NET_DNS 已經都幫我們做好了.</p>
<p>我們只要:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Net/DNS.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ndr</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Net_DNS_Resolver<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$answer</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$ndr</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">search</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;www.OOO.com&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;CNAME&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;pre&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$answer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 獲得的結果</span>
<span style="color: #990000;">Array</span>
<span style="color: #009900;">&#40;</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> Net_DNS_RR_CNAME Object
        <span style="color: #009900;">&#40;</span>
            <span style="color: #009900;">&#91;</span>name<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> www<span style="color: #339933;">.</span>OOO<span style="color: #339933;">.</span>co<span style="color: #339933;">.</span>nz
            <span style="color: #009900;">&#91;</span>type<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> CNAME
            <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> IN
            <span style="color: #009900;">&#91;</span>ttl<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">86400</span>
            <span style="color: #009900;">&#91;</span>rdlength<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">18</span>
            <span style="color: #009900;">&#91;</span>rdata<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> store	XXX�<span style="color: #cc66cc;">3</span>
            <span style="color: #009900;">&#91;</span>cname<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> store<span style="color: #339933;">.</span>XXX<span style="color: #339933;">.</span>com
        <span style="color: #009900;">&#41;</span>
&nbsp;
<span style="color: #009900;">&#41;</span></pre></div></div>

<p>PS, 在 Windows 環境, 請修改 PEAR/NET/DNS/Resolver.php 裡的</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$resolv_conf</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/etc/resolv.conf'</span><span style="color: #339933;">;</span></pre></div></div>

<p>改成</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$resolv_conf</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'D:\Appserv\resolv.conf'</span><span style="color: #339933;">;</span></pre></div></div>

<p>resolv.conf 要加入你的 DNS Server (請用 ipconfig /all 查詢)</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">nameserver 168<span style="color: #339933;">.</span>95<span style="color: #339933;">.</span>192<span style="color: #339933;">.</span>1</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/2066/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 用 PHPUnit 開發體驗II</title>
		<link>http://blog.wabow.com/archives/1856</link>
		<comments>http://blog.wabow.com/archives/1856#comments</comments>
		<pubDate>Fri, 31 Jul 2009 04:12:57 +0000</pubDate>
		<dc:creator>suzy</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[PHPUnit]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1856</guid>
		<description><![CDATA[這次利用 PHPUnit 開發編碼解碼器... 體驗一下... 我需要 Fu ~~~~ 大致的開發過程應該跟大家都差不多, 有為了是否要再細分更多的小 assert function 猶豫了一下, 不過最後還是統統寫在一起. 我的 Encode 規則/步驟 草稿: 1. 濾掉所有不合法的字元,  字串長度若不等於4:  error 2. 把4個字元分別轉成 ASCII code 3. 轉成ASCII code 之後 再檢查要在這個範圍以內: 48-57, 65-90, 97-122 4. 生成檢查碼(第17碼), 規則為四組數字轉為十位元數字相加總和 的 random 其中一個數字. 規則為四組數字轉為十位元數相加總和的最後一個數字 5. 自訂一個 Binary Key, 增加公式的複雜性 6. 將四組數字 "分別"跟 Binary Key 作 XOR 比較 7. 出來的結果 [...]]]></description>
			<content:encoded><![CDATA[<p>這次利用 PHPUnit 開發<strong>編碼解碼器</strong>... 體驗一下... 我需要 Fu ~~~~<br />
<span id="more-1856"></span><br />
大致的開發過程應該跟大家都差不多, 有為了是否要再細分更多的小 assert function 猶豫了一下, 不過最後還是統統寫在一起.</p>
<h4>我的 Encode 規則/步驟 草稿:</h4>
<p>1. 濾掉所有不合法的字元,  字串長度若不等於4:  error<br />
2. 把4個字元分別轉成 ASCII code<br />
3. 轉成ASCII code 之後 再檢查要在這個範圍以內: 48-57, 65-90, 97-122<br />
4. 生成檢查碼(第17碼), <span style="text-decoration: line-through">規則為四組數字轉為十位元數字相加總和 的 random 其中一個數字. </span>規則為四組數字轉為十位元數相加總和的最後一個數字<span style="text-decoration: line-through"> </span><br />
5. 自訂一個 Binary Key, 增加公式的複雜性<br />
6. 將四組數字 "分別"跟 Binary Key 作 XOR 比較<br />
7. 出來的結果 轉成10位元數以後再*檢查碼</p>
<h4>範例:</h4>
<p>Step1: ABCD<br />
Step 2, 3:  ASCII = 65 66 67 68,<br />
Step 4: SUM: 65 + 66 + 67 + 68 = 266,  <span style="text-decoration: line-through">Random 從中選一個數字: 6</span>. 最後一個數字:6<br />
Step 5: 自訂 Binary Key: 1010001<br />
Step 6: 1000001 XOR 1010001 = 0010000, 1000010 XOR 1010001 = 0010011, 1000011 XOR 1010001 = 0010010, 1000100 XOR 1010001 = 0010101<br />
Step 7: 0010000 = 16, 19, 18, 21  = [0096] [0114] [0108] [0126] [6]</p>
<p>寫完以上推論並人工算完第一個範例, 確定可行之後開始寫 PHPunit 的 測試程式.</p>
<h4>過程中產生了一點疑問:</h4>
<p>1. 若我的 output 會變 (因為檢查碼是活的, random 產生的, 也反推的回來), 那麼 PHPUnit 是否有法處理無唯一解的狀況咧??</p>
<p>還請 Jace 指點迷津 <img src='http://blog.wabow.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1856/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 測試先行作業與相關心得 PART2</title>
		<link>http://blog.wabow.com/archives/1852</link>
		<comments>http://blog.wabow.com/archives/1852#comments</comments>
		<pubDate>Thu, 30 Jul 2009 03:14:56 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[單元測試]]></category>
		<category><![CDATA[測試先行]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1852</guid>
		<description><![CDATA[經過上次歡樂（？）的偽噗浪網址轉換器後，本週的作業是「編碼解碼器」；完全沒有測試先行概念的我，首先當然就專注在編碼解碼資源的搜尋上囉！拜 Google 大神後發現也不少推薦的可逆的加密演算法：知名的 AES、3DES，雖然網路上提供許多詳細又完整的 PHP 實踐方式，但是跟此次作業要求的「最後呈現的方式必須為數字」的條件不符。後來稍微看了一下之前在專案中曾經使用過的 XXTEA，發現裡面就提供數字轉字串，與字串轉數字的函數；真是太棒了！ 整個程式的思考概念是從 Andrew 提供的靈感開始：「將 4 個字元的字串分拆為字元，再由單個字元轉換為 4 個數字；最後第 17 個數字則為前 16 個數字的驗證碼」（感謝 Andrew 的分享^^）；不過準備開始的時候發現，測試的部分不知道要如何下手：「測試時，利用 function 編碼後的字串 = function 編碼後的字串？既然用到同一個 function 不是永遠相等嗎？」，所以問了一下 Jace 的用意。才發現我從 function 開始的思考方式就是錯誤的，以「測試先行」的概念來看，應該要先決定編碼過後呈現的字串，反推 function 撰寫的公式！ 可是令我感到困惑的是，既然 function 就是編碼的公式；那「利用 function 編碼後的字串 = 利用公式編碼後的字串」，這還是永遠的等式啊！？我整個呈現鬼打牆的狀態！（暈）「測試先行」的概念可能是著重在思考邏輯的步驟上吧。原本的思考方式是：想 function -&#62; 測試需求 -&#62; 通過測試 -&#62; 完成；但是測試先行的思考方式是：預測結果 -&#62; 推導 function -&#62; 測試需求 -&#62; 通過測試 -&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>經過上次歡樂（？）的偽噗浪網址轉換器後，本週的作業是「編碼解碼器」；完全沒有測試先行概念的我，首先當然就專注在編碼解碼資源的搜尋上囉！拜 Google 大神後發現也不少推薦的可逆的加密演算法：知名的 <a href="http://zh.wikipedia.org/w/index.php?title=%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86&amp;variant=zh-tw" target="_blank">AES</a>、<a href="http://en.wikipedia.org/wiki/Triple_DES" target="_blank">3DES</a>，雖然網路上提供許多詳細又完整的 PHP 實踐方式，但是跟此次作業要求的「最後呈現的方式必須為數字」的條件不符。後來稍微看了一下之前在專案中曾經使用過的 <a href="http://en.wikipedia.org/wiki/XXTEA" target="_blank">XXTEA</a>，發現裡面就提供數字轉字串，與字串轉數字的函數；真是太棒了！</p>
<p><span id="more-1852"></span></p>
<p>整個程式的思考概念是從 <a href="http://blog.wabow.com/archives/author/andrew" target="_blank">Andrew</a> 提供的靈感開始：「將 4 個字元的字串分拆為字元，再由單個字元轉換為 4 個數字；最後第 17 個數字則為前 16 個數字的驗證碼」（感謝 Andrew 的分享^^）；不過準備開始的時候發現，測試的部分不知道要如何下手：「測試時，利用 function 編碼後的字串 = function 編碼後的字串？既然用到同一個 function 不是永遠相等嗎？」，所以問了一下 Jace 的用意。才發現我從 function 開始的思考方式就是錯誤的，以「測試先行」的概念來看，應該要先決定編碼過後呈現的字串，反推 function 撰寫的公式！</p>
<p>可是令我感到困惑的是，既然 function 就是編碼的公式；那「利用 function 編碼後的字串 = 利用公式編碼後的字串」，這還是永遠的等式啊！？我整個呈現鬼打牆的狀態！（暈）「測試先行」的概念可能是著重在思考邏輯的步驟上吧。原本的思考方式是：想 function -&gt; 測試需求 -&gt; 通過測試 -&gt; 完成；但是測試先行的思考方式是：預測結果 -&gt; 推導 function -&gt; 測試需求 -&gt; 通過測試 -&gt; 完成。怎麼看都是後者比較花時間！（囧）</p>
<p>原本對數學就苦手的我，對於推導公式的過程是完全的頭大啊！（囧）因為昨天跟 Jace 討論的時候有提到查表法，好像並沒有限制這個方法；索性我就把 XXTEA 的公式做成密碼表，根據這個密碼表進行編碼解碼的動作囉～這次的作業還不僅是練習測試先行的概念，同時帶有專案管理的概念，要把 Jace 模擬為客戶，並向他提出需求上沒有的問題；是老師的用心良苦，也是學生的額外課題（囧）！</p>
<p>對我來說測試先行的優點在於，思考的邏輯更為清晰；就好像畫素描一樣，必須先從大輪廓開始，在一步步修飾細部才能唯妙唯肖。缺點是必須經過比較多步驟，可能會增加許多不必要的時間。畢竟當畫素描是一個有限定時間的考試時，雖然慢工出細活，但能不能拿到高分就難說了～^^|||</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/tdd2_090804.zip">測試先行作業 PART2 下載</a>（090804修正程式）</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1852/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[課程分享] PHPUnit入門-課後分享</title>
		<link>http://blog.wabow.com/archives/1821</link>
		<comments>http://blog.wabow.com/archives/1821#comments</comments>
		<pubDate>Mon, 27 Jul 2009 06:47:58 +0000</pubDate>
		<dc:creator>ingrid</dc:creator>
				<category><![CDATA[教育訓練]]></category>
		<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1821</guid>
		<description><![CDATA[周末假日前的午後， 我們再次相聚於果子咖啡。 大夥仍舊是人手一台notebook， 果然是資訊人的標準配備。 就像安全氣囊之於車子一樣... 小鐵老師神來一筆的幽默， 讓原本生硬的主題多了一分輕鬆感。 這次的上課人數較上回多了點， 在果子的幫忙下做了最佳的位置排列，感謝果子~ 也感謝大家的包涵^^ 認真的男人最帥氣~ (這兩位朋友上回也有來捧場喔!) 課程中帶入時事， Dell 事件帶給大家的警惕與學習。 測試是必須的，也很重要... 大家熱烈討論中， 謝謝各路高手的鼎力相助! (上圖左這位大哥也教了我們很多呢~鞠~~) 上課最珍貴的地方除了可以學到老師的專業， 另外就是大夥的相互討論與分享~ 這次又認識了一些新朋友， 無論是第一次或再次參與哇寶的課程， 希望本課程對大家都能有所幫助喔~ 若對於課程有任何心得或建議， 也歡迎大家與我們分享。 期待下一次再與你相聚~^^ *課程簡報： [附註] 大澤木小鐵老師的e-mail : jaceju@wabow.com 大家有任何程式技術上的疑難雜症， 歡迎來信與小鐵老師討論喔~!]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_11.jpg"><img class="aligncenter size-medium wp-image-1825" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_11-300x214.jpg" alt="0724_1" width="300" height="214" /></a></p>
<p>周末假日前的午後，<br />
我們再次相聚於果子咖啡。</p>
<p><span id="more-1821"></span></p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_21.jpg"><img class="aligncenter size-medium wp-image-1826" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_21-300x210.jpg" alt="0724_2" width="300" height="210" /></a></p>
<p>大夥仍舊是人手一台notebook，<br />
果然是資訊人的標準配備。<br />
就像安全氣囊之於車子一樣...</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_3.jpg"><img class="aligncenter size-medium wp-image-1827" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_3-300x213.jpg" alt="0724_3" width="300" height="213" /></a></p>
<p>小鐵老師神來一筆的幽默，<br />
讓原本生硬的主題多了一分輕鬆感。</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_4.jpg"><img class="aligncenter size-medium wp-image-1828" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_4-300x212.jpg" alt="0724_4" width="300" height="212" /></a></p>
<p>這次的上課人數較上回多了點，<br />
在果子的幫忙下做了最佳的位置排列，感謝果子~<br />
也感謝大家的包涵^^</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_8.jpg"><img class="aligncenter size-medium wp-image-1829" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_8-300x269.jpg" alt="0724_8" width="300" height="269" /></a></p>
<p>認真的男人最帥氣~<br />
<span style="color: #333399">(這兩位朋友上回也有來捧場喔!)</span></p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_7.jpg"><img class="aligncenter size-medium wp-image-1831" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_7-300x204.jpg" alt="0724_7" width="300" height="204" /></a></p>
<p>課程中帶入時事，<br />
Dell 事件帶給大家的警惕與學習。<br />
測試是必須的，也很重要...</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_111.jpg"><img class="aligncenter size-medium wp-image-1832" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_111-300x260.jpg" alt="0724_11" width="300" height="260" /></a></p>
<p>大家熱烈討論中，<br />
謝謝各路高手的鼎力相助!<br />
<span style="color: #333399">(上圖左這位大哥也教了我們很多呢~鞠~~)<br />
</span>上課最珍貴的地方除了可以學到老師的專業，<br />
另外就是大夥的相互討論與分享~</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/0724_12.jpg"><img class="aligncenter size-medium wp-image-1833" src="http://blog.wabow.com/wp-content/uploads/2009/07/0724_12-224x300.jpg" alt="0724_12" width="224" height="300" /></a></p>
<p>這次又認識了一些新朋友，<br />
無論是第一次或再次參與哇寶的課程，<br />
希望本課程對大家都能有所幫助喔~<br />
若對於課程有任何心得或建議，<br />
也歡迎大家與我們分享。</p>
<p>期待下一次再與你相聚~^^</p>
<p>*課程簡報：<br />
<object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phpunit-090720055328-phpapp02&#038;stripped_title=phpunit" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phpunit-090720055328-phpapp02&#038;stripped_title=phpunit" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></p>
<p><span style="color: #808080">[附註]<br />
大澤木小鐵老師的e-mail :</span> <a href="mailto:jaceju@wabow.com">jaceju@wabow.com</a><br />
<span style="color: #808080">大家有任何程式技術上的疑難雜症，<br />
歡迎來信與小鐵老師討論喔~!</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1821/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 用 PHPUnit 開發初體驗</title>
		<link>http://blog.wabow.com/archives/1788</link>
		<comments>http://blog.wabow.com/archives/1788#comments</comments>
		<pubDate>Thu, 23 Jul 2009 06:26:34 +0000</pubDate>
		<dc:creator>suzy</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[PHPUnit]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1788</guid>
		<description><![CDATA[PHPUnit =  在黑黑的 console 下寫程式 總共花的時間(去除掉安裝 PHPUnit), 大概是 2小時又多一點吧 我感受到使用 PHPUnit 的優點 寫到第九, 第十個條件的時候, 我發現我可以一次測全部十個, 這樣一次到位的感覺還不錯. 在過去我的作法就是一個一個試, 跟 "憑經驗" 囉. 因為寫程式常常會發生: 新增了OOO, 舊的XXX壞了, 只好再重修, 再測試... 有時隔段時間再寫, 遇到這樣的狀況真的還滿頭痛的. 我想等到假如有100條件的時候, 測試先行這個優勢會更明顯. 另外, 我有兩個問題想問 Jace 的是: 第8, 9 一定要用 TDD 的用意是? 還有結果我沒有用到 testBuildImage() 跟 testBuildYoutube() 耶 ..... 那我要怎麼用它們呢? 心得 1. 單元測試 我想可能就像"條列"可以幫助思考一樣吧, 把一個很複雜的東西打散成很多個小部份, 等到全部的小部份完成, 再組合起來即是(接近)完成, 簡單明瞭. 以提升人類處理事件的效能來看, 可能會真的會比較快也不一定喔!? [...]]]></description>
			<content:encoded><![CDATA[<p>PHPUnit =  在黑黑的 console 下寫程式</p>
<p>總共花的時間(去除掉安裝 PHPUnit), 大概是 2小時又多一點吧</p>
<p><a href="http://blog.wabow.com/wp-content/uploads/2009/07/未命名-31.jpg"><img class="alignnone size-full wp-image-1816" src="http://blog.wabow.com/wp-content/uploads/2009/07/未命名-31.jpg" alt="未命名-3" width="829" height="277" /></a></p>
<p><span id="more-1788"></span></p>
<h2>我感受到使用 PHPUnit 的優點</h2>
<p>寫到第九, 第十個條件的時候, 我發現我可以一次測全部十個, 這樣一次到位的感覺還不錯. 在過去我的作法就是一個一個試, 跟 "憑經驗" 囉.</p>
<p>因為寫程式常常會發生: 新增了OOO, 舊的XXX壞了, 只好再重修, 再測試... 有時隔段時間再寫, 遇到這樣的狀況真的還滿頭痛的.</p>
<p><span style="color: #ff6600"><strong>我想等到假如有100條件的時候, 測試先行這個優勢會更明顯.</strong></span><br />
另外, 我有兩個問題想問 Jace 的是:</p>
<ul>
<li>第8, 9 一定要用 TDD 的用意是?</li>
<li>還有結果我沒有用到 testBuildImage() 跟 testBuildYoutube() 耶 <img src='http://blog.wabow.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ..... 那我要怎麼用它們呢?</li>
</ul>
<h2>心得</h2>
<p>1. 單元測試 我想可能就像<span style="color: #ff6600">"條列"可以幫助思考</span>一樣吧, 把一個很複雜的東西打散成很多個小部份, 等到全部的小部份完成, 再組合起來即是(接近)完成, 簡單明瞭. 以提升人類處理事件的效能來看, 可能會真的會比較快也不一定喔!?<br />
2. 第二個我覺得會比較快一些的理由:  當我們單純地只去做某一部份, 以 performance 來說, 如果每次 reload 都快個 2 秒, 那100次就快200秒囉.<br />
或許在這一次的作業, 我們感受不出來很大的差別, 但假如 我們在一個已存在且龐大的 framwork 架構下寫程式, 而每一次 reload 都要連資料庫, 跑 3-5個 sql, 然後才去執行程式, 長期下來就會慢滿多囉.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1788/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 測試先行感想 Part One</title>
		<link>http://blog.wabow.com/archives/1792</link>
		<comments>http://blog.wabow.com/archives/1792#comments</comments>
		<pubDate>Thu, 23 Jul 2009 06:01:07 +0000</pubDate>
		<dc:creator>abu</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[PHPUnit]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1792</guid>
		<description><![CDATA[恩，這次的題目『仿噗浪之輸出字串替換』，感覺比較有趣部份，就是替換過程，為了讓流程簡化當然正規式是不二人選，如同阿丹提到的，這是場與正規式的拉力戰，戰勝正規式的就能戰勝噗浪(是這樣說的嗎？)，一方面使用PHPUnit提供的檢測方式，一方面使用傳統的Reload大法檢測，說真的，感覺不出來差別，真的要說就是，一邊是全彩FullHD這樣，畫面很漂亮，瀏覽器五顏六色這樣，一邊是Dos畫面，跟Mud一樣，會出現偶發的Perform(施展外功)帶出來的彩色文字，看到都是綠字的時候代表對方被你打死了或是中毒很深代表檢測通過了，目前有感受到一個好處，就是『看到是對的，不一定是對的』↓ 例如：在試著轉換輸入字串時，網頁上看到的樣式是 Yahoo 看起來是對了，but.....！實際上是錯，因為轉換出來的其實是 &#60;a href=&#34;http://Yahoo&#34;&#62;Yahoo&#60;/a&#62;&#60;a href=&#34;&#34;&#62;&#60;/a&#62; 為什麼輸出字串會發生錯誤呢？因為我程式寫錯了 (廢話) 重點是，網頁上瀏覽的結果是"對的"，實際上卻是錯的，當透過PHPUnit檢測，就能正確的顯示錯誤 所以目前的感受，是PHPUnit在Html檢測上比較實用？！as 阿丹`s talk (誠如阿丹所言) (請suzy小老師幫看文法是否有誤)，我應該也沒那個View....尚不得其單元奧義 囧]]></description>
			<content:encoded><![CDATA[<p>恩，這次的題目『仿噗浪之輸出字串替換』，感覺比較有趣部份，就是替換過程，為了讓流程簡化當然正規式是不二人選<span id="more-1792"></span>，如同阿丹提到的，這是場與正規式的拉力戰，戰勝正規式的就能戰勝噗浪(是這樣說的嗎？)，一方面使用PHPUnit提供的檢測方式，一方面使用傳統的Reload大法檢測，說真的，感覺不出來差別，真的要說就是，一邊是全彩FullHD這樣，畫面很漂亮，瀏覽器五顏六色這樣，一邊是Dos畫面，跟Mud一樣，會出現偶發的Perform(施展外功)帶出來的彩色文字，看到都是綠字的時候<span style="text-decoration: line-through;">代表對方被你打死了或是中毒很深</span>代表檢測通過了，目前有感受到一個好處，就是『看到是對的，不一定是對的』↓</p>
<p>例如：在試著轉換輸入字串時，網頁上看到的樣式是<br />
<a href="http://Yahoo">Yahoo</a><a href=""></a><br />
看起來是對了，but.....！實際上是錯，因為轉換出來的其實是</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://Yahoo&quot;</span>&gt;</span>Yahoo<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span></pre></div></div>

<p>為什麼輸出字串會發生錯誤呢？因為我程式寫錯了 (廢話)<br />
重點是，網頁上瀏覽的結果是"對的"，實際上卻是錯的，當透過PHPUnit檢測，就能正確的顯示錯誤</p>
<p>所以目前的感受，是PHPUnit在Html檢測上比較實用？！as 阿丹`s talk (誠如阿丹所言)  (請suzy小老師幫看文法是否有誤)，我應該也沒那個View....尚不得其單元奧義 囧</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1792/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[心得]實做TDD</title>
		<link>http://blog.wabow.com/archives/1765</link>
		<comments>http://blog.wabow.com/archives/1765#comments</comments>
		<pubDate>Thu, 23 Jul 2009 03:38:55 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1765</guid>
		<description><![CDATA[上完jace所介紹的單元測試(測試先行)以及PHPUNIT的操作方法的課程後，先嘗試在公司的電腦(WINSOWS OS)安裝PEAR，WINDOWS上使用PEAR來安裝服務軟體是比較簡單的方法。 參考這個網站來安裝卻一直發生找不到相關路徑的錯誤，就算手動指定也是一樣。後來回家後改在自家電腦安裝，先參考這篇安裝完 PHP5 開發環境，然後成功安裝PEAR，最後成功把phpunit也安裝完成。 簡單註記一下用PEAR安裝phpunit的指令如下︰ pear channel-discover pear.phpunit.de pear install -a phpunit/PHPUnit 實際使用phpunit來實做TDD(Test-Driven Development)，以網址自動解析功能來說，如果不使用單元測試的情況下話，要測試單一function在執行上是否有問題，必須要先作一個簡單的輸入框頁面，然後針對此頁面編寫針對輸入值作後續處理的code，然後構思各種輸入值的可能來測試function是否有誤，然後在逐步去修改function中邏輯。如果是使用單元測試的話，可以不用製作輸入框的頁面來測試，只需要依照格式編寫測試程式，再透過provider的模式將要測試的資料透過陣列方式逐一填入後再逐項測試。 我覺得透過單元測試的作法對於function的測試上比較有一個依循的規則，同時也可以紀錄在測試這個function時有用哪些資料型態測試過無誤，對隔了很長時間後如果有追加功能時有比較清楚這個function當初有做了哪些資料的測試以方便編寫追加功能時的參考依據。因此我覺得單元測試的確有其幫助程式編寫上邏輯釐清及確保功能無誤的作用，不過如果案子規模較小且時程上比較趕的時候，還是要斟酌是否要執行單元測試，這在實務上的確還是有需要考量的地方。]]></description>
			<content:encoded><![CDATA[<p>上完jace所介紹的單元測試(測試先行)以及PHPUNIT的操作方法的課程後，先嘗試在公司的電腦(WINSOWS OS)安裝PEAR，WINDOWS上使用PEAR來安裝服務軟體是比較簡單的方法。<span id="more-1765"></span></p>
<p>參考<a href="http://blog.wu-boy.com/2009/03/14/970/">這個網站</a>來安裝卻一直發生找不到相關路徑的錯誤，就算手動指定也是一樣。後來回家後改在自家電腦安裝，先參考<a href="http://www.jaceju.net/blog/?p=271">這篇</a>安裝完 PHP5 開發環境，然後成功安裝PEAR，最後成功把phpunit也安裝完成。<br />
簡單註記一下用PEAR安裝phpunit的指令如下︰</p>
<blockquote><p>pear channel-discover pear.phpunit.de<br />
pear install -a phpunit/PHPUnit</p></blockquote>
<p>實際使用phpunit來實做TDD(Test-Driven Development)，以網址自動解析功能來說，如果不使用單元測試的情況下話，要測試單一function在執行上是否有問題，必須要先作一個簡單的輸入框頁面，然後針對此頁面編寫針對輸入值作後續處理的code，然後構思各種輸入值的可能來測試function是否有誤，然後在逐步去修改function中邏輯。如果是使用單元測試的話，可以不用製作輸入框的頁面來測試，只需要依照格式編寫測試程式，再透過provider的模式將要測試的資料透過陣列方式逐一填入後再逐項測試。</p>
<p>我覺得透過單元測試的作法對於function的測試上比較有一個依循的規則，同時也可以紀錄在測試這個function時有用哪些資料型態測試過無誤，對隔了很長時間後如果有追加功能時有比較清楚這個function當初有做了哪些資料的測試以方便編寫追加功能時的參考依據。因此我覺得單元測試的確有其幫助程式編寫上邏輯釐清及確保功能無誤的作用，不過如果案子規模較小且時程上比較趕的時候，還是要斟酌是否要執行單元測試，這在實務上的確還是有需要考量的地方。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1765/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 測試先行作業與相關心得</title>
		<link>http://blog.wabow.com/archives/1781</link>
		<comments>http://blog.wabow.com/archives/1781#comments</comments>
		<pubDate>Thu, 23 Jul 2009 02:40:19 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[單元測試]]></category>
		<category><![CDATA[測試先行]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1781</guid>
		<description><![CDATA[「測試先行開發模式」其實在上週的《[心得] 單元測試相關心得：單元測試與軟體開發》就已經提到，Wiki 也把它相關的正反面評價也寫的很清楚；本週的課題作業就是要試著以這樣的模式進行開發。不過因為我跟阿布覺得「測試先行」這個概念實在很弔詭，所以非常幸運的還是使用原始的開發模式。最後由 Suzy 做實驗組，我們為對照組的方式；實際比較二種開發模式的不同。 課題作業的內容，是仿造知名微網誌噗浪的訊息輸入，在輸入符合某些 Url 規則時，自動轉換為 HTML 語言。當然當我們需要判斷某些特殊規則的時候，非常直覺的一定會想到大家的好朋友「正規式」！但也因為正規式的出現，有點模糊了原本體驗「測試先行」的目的，大部分寫作業的時間都耗在正規式的判斷與寫法...正規式是程式語言界中的火星文啊！（吼）Wiki 其實已經提供很好的正規式說明，不過「正則表達式30分鐘入門教程」提供更完整詳細的說明，尤其是「後向引用」更是以前想都想不到的使用方式！「Regular Expression Library」提供很多網路前輩們已經寫好的正規式判斷，算是非常完整的正規式資料庫唷！ 因為其實我還是用傳統的 Redo &#38; Debug 的方式，所以對測試先行並沒有特別的感覺，反而是採用「測試最後行」（有這種說法嗎？）的方式（因為最後幾題 Jace 指定要用單元測試的方式...），把 function 都寫好以後才開始寫測試程式；不過在全部測試時，Provider 提供的批次測試的確有比程式寫死或是一般網頁輸入要來的方便許多。算是有贏傳統開發模式的地方吧～但是我還是覺得使用測試先行應該會比較花費時間耶...（囧）果然這種嚴謹的開發模式，不是我這種目光短淺的人所能了解的吧！（沒有 View，噗） 測試先行作業下載]]></description>
			<content:encoded><![CDATA[<p>「<a href="http://zh.wikipedia.org/w/index.php?title=%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91&amp;variant=zh-tw" target="_blank">測試先行開發模式</a>」其實在上週的《<a href="http://blog.wabow.com/archives/1755" target="_blank">[心得] 單元測試相關心得：單元測試與軟體開發</a>》就已經提到，Wiki 也把它相關的正反面評價也寫的很清楚；本週的課題作業就是要試著以這樣的模式進行開發。不過因為我跟阿布覺得「測試先行」這個概念實在很弔詭，所以<span style="text-decoration: line-through;">非常幸運的</span>還是使用原始的開發模式。最後由 Suzy 做實驗組，我們為對照組的方式；實際比較二種開發模式的不同。</p>
<p><span id="more-1781"></span>課題作業的內容，是仿造知名微網誌<a href="http://www.plurk.com/" target="_blank">噗浪</a>的訊息輸入，在輸入符合某些 Url 規則時，自動轉換為 HTML 語言。當然當我們需要判斷某些特殊規則的時候，非常直覺的一定會想到大家的好朋友「<a href="http://zh.wikipedia.org/w/index.php?title=%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F&amp;variant=zh-tw" target="_blank">正規式</a>」！但也因為正規式的出現，有點模糊了原本體驗「測試先行」的目的，大部分寫作業的時間都耗在正規式的判斷與寫法...正規式是程式語言界中的<a href="http://komica.dyndns.org/wiki/?%E7%81%AB%E6%98%9F%E6%96%87" target="_blank">火星文</a>啊！（吼）Wiki 其實已經提供很好的正規式說明，不過「<a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm" target="_blank">正則表達式30分鐘入門教程</a>」提供更完整詳細的說明，尤其是「<a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#backreference" target="_blank">後向引用</a>」更是以前想都想不到的使用方式！「<a href="http://regexlib.com/Default.aspx" target="_blank">Regular Expression Library</a>」提供很多網路前輩們已經寫好的正規式判斷，算是非常完整的正規式資料庫唷！</p>
<p>因為其實我還是用傳統的 Redo &amp; Debug 的方式，所以對測試先行並沒有特別的感覺，反而是採用「測試最後行」（有這種說法嗎？）的方式（因為最後幾題 Jace 指定要用單元測試的方式...），把 function 都寫好以後才開始寫測試程式；不過在全部測試時，Provider 提供的批次測試的確有比程式寫死或是一般網頁輸入要來的方便許多。算是有贏傳統開發模式的地方吧～但是我還是覺得使用測試先行應該會比較花費時間耶...（囧）果然這種嚴謹的開發模式，不是我這種目光短淺的人所能了解的吧！（沒有 View，噗）</p>
<p><a href="../wp-content/uploads/2009/07/tdd.zip">測試先行作業下載</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1781/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得]單元測試</title>
		<link>http://blog.wabow.com/archives/1758</link>
		<comments>http://blog.wabow.com/archives/1758#comments</comments>
		<pubDate>Thu, 16 Jul 2009 07:22:54 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1758</guid>
		<description><![CDATA[前言 一個網站的完成，從初期與客戶詢問需求、撰寫相關文件，到中期的版面設計及程式撰寫，到後期網站測試、驗收文件撰寫，最後專案結案及後續維護，是一個很長的生命週期。每個環節的執行是否完善，都深深影響到最後網站專案是否如期完成。那個到底何謂單元測試呢？其實就是一種程式面的測試。說到網站測試大部分直覺想到的就是依照當初開的需求文件逐項操作網站各項功能，然後一一把有問題的部份條列下來，在交給相關部門作修改，這就是一般所謂QA部門每天所做的工作。等到相關部門逐項處理完畢後就再次回報給QA，也就是作複審的動作，如果沒新發現的問題就表示內部測試完畢，可以通知客戶開始測試了。那麼單元測試跟一般的測試有何不同，讓我們來看看。 何謂單元測試 單元測試的單元，是程式中不可再分割的單元，通常是函數或類別的方法。最基本的進行方式是傳參數給函數/方法，然後檢查他的反應是否正確。其特別之處是在網站開始動工前執行的動作，也就是先行測試開發的概念。當整個網站程式尚未開始編寫前，先規劃出要測試的功能部份有哪些，如果都測試無誤才開始著手網站的程式編寫。或許有人會問，為何不等網站程式全部編寫完畢後再來作測試？其實單元測試就像是網站整體架構及流程的預覽動作，把要測的項目先釐清出來，如此之後再開始著手編寫程式時就不至於偏離網站需求太遠，這就是單元測試的魅力。 單元測試的工具 常見的工具如JUnit(http://www.junit.org/)或是PHPUNIT(http://www.phpunit.de/)，都是很常見的，端看你的開發環境是用哪一套。如果想學習JUnit的用法可參考JUnit 學習筆記(http://caterpillar.onlyfun.net/Gossip/JUnit/JUnitGossip.htm)；如果想學習PHPUNIT可以按此報名於7月24日哇寶資訊技術總監JACE所開辦的PHPUnit 入門講座，人數有限，盡早報名。 一些參考網站 單元測試解析 http://jyhshin.pixnet.net/blog/post/28084838 單元測試及先行測試開發 http://www.microsoft.com/taiwan/msdn/library/2003/apr-2003/csharp03202003.htm 使用單元測試 http://msdn.microsoft.com/zh-tw/library/ms182515(VS.80).aspx]]></description>
			<content:encoded><![CDATA[<h3>前言</h3>
<p>一個網站的完成，從初期與客戶詢問需求、撰寫相關文件，到中期的版面設計及程式撰寫，到後期網站測試、驗收文件撰寫，最後專案結案及後續維護，是一個很長的生命週期。每個環節的執行是否完善，都深深影響到最後網站專案是否如期完成。那個到底何謂單元測試呢？其實就是一種程式面的測試。說到網站測試大部分直覺想到的就是依照當初開的需求文件逐項操作網站各項功能，然後一一把有問題的部份條列下來，在交給相關部門作修改，這就是一般所謂QA部門每天所做的工作。等到相關部門逐項處理完畢後就再次回報給QA，也就是作複審的動作，如果沒新發現的問題就表示內部測試完畢，可以通知客戶開始測試了。那麼單元測試跟一般的測試有何不同，讓我們來看看。<span id="more-1758"></span></p>
<h3>何謂單元測試</h3>
<p>單元測試的單元，是程式中不可再分割的單元，通常是函數或類別的方法。最基本的進行方式是傳參數給函數/方法，然後檢查他的反應是否正確。其特別之處是在網站開始動工前執行的動作，也就是先行測試開發的概念。當整個網站程式尚未開始編寫前，先規劃出要測試的功能部份有哪些，如果都測試無誤才開始著手網站的程式編寫。或許有人會問，為何不等網站程式全部編寫完畢後再來作測試？其實單元測試就像是網站整體架構及流程的預覽動作，把要測的項目先釐清出來，如此之後再開始著手編寫程式時就不至於偏離網站需求太遠，這就是單元測試的魅力。</p>
<h3>單元測試的工具</h3>
<p>常見的工具如JUnit(<a href="http://www.junit.org/">http://www.junit.org/</a>)或是PHPUNIT(<a href="http://www.phpunit.de/">http://www.phpunit.de/</a>)，都是很常見的，端看你的開發環境是用哪一套。如果想學習JUnit的用法可參考JUnit 學習筆記(<a href="http://caterpillar.onlyfun.net/Gossip/JUnit/JUnitGossip.htm">http://caterpillar.onlyfun.net/Gossip/JUnit/JUnitGossip.htm</a>)；如果想學習PHPUNIT可以<a href="http://registrano.com/events/phpunit-basic">按此</a>報名於7月24日哇寶資訊技術總監JACE所開辦的PHPUnit 入門講座，人數有限，盡早報名。</p>
<h3>一些參考網站</h3>
<p>單元測試解析 <a href="http://jyhshin.pixnet.net/blog/post/28084838">http://jyhshin.pixnet.net/blog/post/28084838</a></p>
<p>單元測試及先行測試開發 <a href="http://www.microsoft.com/taiwan/msdn/library/2003/apr-2003/csharp03202003.htm">http://www.microsoft.com/taiwan/msdn/library/2003/apr-2003/csharp03202003.htm</a></p>
<p>使用單元測試 <a href="http://msdn.microsoft.com/zh-tw/library/ms182515(VS.80).aspx">http://msdn.microsoft.com/zh-tw/library/ms182515(VS.80).aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1758/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[心得] 單元測試相關心得：單元測試與軟體開發</title>
		<link>http://blog.wabow.com/archives/1755</link>
		<comments>http://blog.wabow.com/archives/1755#comments</comments>
		<pubDate>Thu, 16 Jul 2009 06:33:09 +0000</pubDate>
		<dc:creator>daniel</dc:creator>
				<category><![CDATA[軟體測試]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[單元測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1755</guid>
		<description><![CDATA[上週經過 Jace 介紹 PHPUnit 的教育訓練，稍微了解關於 PHP 在單元測試時，使用 PHPUnit 應該如何運用。雖然開場的時候有簡單解釋一下什麼是「單元測試」，但是因為小弟在下資質駑鈍，完全處於一種有聽沒有懂的狀態；所以後來 Wiki 了一下，才知道單元測試僅是複雜的軟體測試的一小部分，而軟體測試，又只是龐大的軟體開發中的一個環節而已！（暈） 在茫茫網海收集資料的過程中，又發現到「Continuous Integration」這個軟體開發時的一種專案管理方式，它也十分重視測試的重要性；同時整合統一的版本控管系統、以及配合開發人員的撰寫精巧易維護，低耦合性的程式碼、最後經由一定時間自動從版本控管系統把程式拉出來測試，自動 build，自動通知相關人員的全自動化處理，做最完善的軟體專案流程控管。聽起來感覺上是非常理想又完美的軟體開發方式！（夢幻？） 太過深入研究軟體開發，似乎會有一種沒完沒了的感覺...（囧）單純就「單元測試」來說，是對於程式最小單位的類別，針對其內部邏輯正確性的驗證；所以通常一個程式類別，就應該伴隨著一個針對該類別，檢驗其內部方法的測試類別。因為單元測試的特色：徹底性、可重複性、獨立性與專業性，讓需要經由大量資料測試的程式，透過單元測試的方式達到自動化，並有效減少正式上線後錯誤的發生，達到令程式變得更加完美的目的。 然而現實環境通常沒有辦法盡如人意，撰寫單元測試就意味著必須花費額外的工時，在一秒鐘幾十萬上下的台灣似乎是一件不可能的任務；更不用提那夢幻的軟體開發方式 Continuous Integration 了...這樣的現實狀況似乎有呼應到教育訓練結尾的結論：「小案子就放它一馬吧；對 Web 開發而言，一般的 CRUD 並沒有特別需要作測試」。 不過隨著網際網路的發達，Web 的開發好像也愈來愈複雜；在 Google 都放出 Google Operating System 的現在，愈來愈有一種「網路是充滿無限可能，實現夢想（我要成為網路王？）的最佳舞台」的感覺！或許在不久的將來，程式的困難度與複雜度，讓測試變的更加困難時，單元測試的導入會是很好的解決方案...吧？ P.S 另外對於教育訓練中提到的「測試先行開發模式」，我深深的感到困惑；如果說在開始撰寫程式碼前必須先寫測試，那單元測試中需要引入的類別要從何而來啊？不先寫程式類別，要怎麼做 Test case 呢？ 參考資料： Midnight Blog Continuous Integration 當紅炸子雞 Continuous Integration SuiFei 單元測試基礎知識]]></description>
			<content:encoded><![CDATA[<p>上週經過 Jace 介紹 PHPUnit 的教育訓練，稍微了解關於 PHP 在單元測試時，使用 <a href="http://www.phpunit.de/" target="_blank">PHPUnit</a> 應該如何運用。雖然開場的時候有簡單解釋一下什麼是「單元測試」，但是因為小弟在下資質駑鈍，完全處於一種有聽沒有懂的狀態；所以後來 Wiki 了一下，才知道<a href="http://zh.wikipedia.org/w/index.php?title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95&amp;variant=zh-tw" target="_blank">單元測試</a>僅是複雜的<a href="http://zh.wikipedia.org/w/index.php?title=%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95&amp;variant=zh-tw" target="_blank">軟體測試</a>的一小部分，而軟體測試，又只是龐大的<a href="http://zh.wikipedia.org/w/index.php?title=%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91&amp;variant=zh-tw" target="_blank">軟體開發</a>中的一個環節而已！（暈）</p>
<p><span id="more-1755"></span></p>
<p>在茫茫網海收集資料的過程中，又發現到「<a href="http://martinfowler.com/articles/continuousIntegration.html" target="_blank">Continuous Integration</a>」這個軟體開發時的一種專案管理方式，它也十分重視測試的重要性；同時整合統一的版本控管系統、以及配合開發人員的撰寫精巧易維護，低耦合性的程式碼、最後經由一定時間自動從版本控管系統把程式拉出來測試，自動 build，自動通知相關人員的全自動化處理，做最完善的軟體專案流程控管。聽起來感覺上是非常理想又完美的軟體開發方式！（夢幻？）</p>
<p>太過深入研究軟體開發，似乎會有一種沒完沒了的感覺...（囧）單純就「單元測試」來說，是對於程式最小單位的類別，針對其內部邏輯正確性的驗證；所以通常一個程式類別，就應該伴隨著一個針對該類別，檢驗其內部方法的測試類別。因為單元測試的特色：徹底性、可重複性、獨立性與專業性，讓需要經由大量資料測試的程式，透過單元測試的方式達到自動化，並有效減少正式上線後錯誤的發生，達到令程式變得更加完美的目的。</p>
<p>然而現實環境通常沒有辦法盡如人意，撰寫單元測試就意味著必須花費額外的工時，在一秒鐘幾十萬上下的台灣似乎是一件不可能的任務；更不用提那夢幻的軟體開發方式 Continuous Integration 了...這樣的現實狀況似乎有呼應到教育訓練結尾的結論：「小案子就放它一馬吧；對 Web 開發而言，一般的 CRUD 並沒有特別需要作測試」。</p>
<p>不過隨著網際網路的發達，Web 的開發好像也愈來愈複雜；在 Google 都放出 <a href="http://googlesystem.blogspot.com/" target="_blank">Google Operating System</a> 的現在，愈來愈有一種「網路是充滿無限可能，實現夢想（<a class="wpGallery" href="http://blog.wabow.com/wp-content/uploads/2009/07/one_web.png">我要成為網路王？</a>）的最佳舞台」的感覺！或許在不久的將來，程式的困難度與複雜度，讓測試變的更加困難時，單元測試的導入會是很好的解決方案...吧？</p>
<p>P.S 另外對於教育訓練中提到的「<a href="http://zh.wikipedia.org/w/index.php?title=%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91&amp;variant=zh-tw" target="_blank">測試先行開發模式</a>」，我深深的感到困惑；如果說在開始撰寫程式碼前必須先寫測試，那單元測試中需要引入的類別要從何而來啊？不先寫程式類別，要怎麼做 <a href="http://en.wikipedia.org/wiki/Test_case" target="_blank">Test case</a> 呢？</p>
<p>參考資料：</p>
<ul>
<li>Midnight Blog <a href="http://blog.pbg4.org/2007/4/24/continuous-integration" target="_blank">Continuous Integration</a></li>
<li>當紅炸子雞 <a href="http://www.josephj.com/entry.php?id=251" target="_blank">Continuous Integration</a></li>
<li>SuiFei <a href="http://www.cnblogs.com/chinasf/archive/2008/03/07/1094334.html" target="_blank">單元測試基礎知識</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1755/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[心得] Unit Test</title>
		<link>http://blog.wabow.com/archives/1748</link>
		<comments>http://blog.wabow.com/archives/1748#comments</comments>
		<pubDate>Thu, 16 Jul 2009 06:07:34 +0000</pubDate>
		<dc:creator>abu</dc:creator>
				<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1748</guid>
		<description><![CDATA[上週五參與了哇寶主辦的一場PHPUnit 入門.....聽完jace大師的講解，大致瞭解什麼是Unit Test，以及該如何開始Unit Test，輔助工具有哪些，以前到現在其實並沒有接觸過Unit Test，專案也都是直接"摳"到完，在邊瞭解Unit Test過程中，會想到是不是存在著問題， 1是時間，寫完為了"測試"專案所花費的時間，會不會就直接超過專案呢？2是盲點，當撰寫程式過程中，設計師自己思考後的邏輯，按照合理及各種可能性流程，最後再來個按照相同邏輯，寫出來的測試，這樣情況下，測試的實用度是否存在？ 不過另一個角度來看，Unit Test可以當作"範例"，測試過程其實也就是說明程式是如何運作，可以讓其他人容易瞭解你的流程，另外就是遇到一些重複性很高的測試等等。 不過可能是還沒親身搭配專案使用過，目前對於Unit Test實用性還是一知半解，看不到他深處的美好，就像尚未接觸樣板概念前，完全不瞭解他的實用度，直到實際試用過後，才能深深瞭解重要，不過依照目前接觸專案的等級，好像還用不到Unit Test，有機會 .... 再來用看看吧，因為 『小案子就放它一馬吧』！！！！]]></description>
			<content:encoded><![CDATA[<p>上週五參與了哇寶主辦的一場PHPUnit 入門.....<span id="more-1748"></span>聽完jace大師的講解，大致瞭解什麼是Unit Test，以及該如何開始Unit Test，輔助工具有哪些，以前到現在其實並沒有接觸過Unit Test，專案也都是直接"摳"到完，在邊瞭解Unit Test過程中，會想到是不是存在著問題， 1是時間，寫完為了"測試"專案所花費的時間，會不會就直接超過專案呢？2是盲點，當撰寫程式過程中，設計師自己思考後的邏輯，按照合理及各種可能性流程，最後再來個按照相同邏輯，寫出來的測試，這樣情況下，測試的實用度是否存在？</p>
<p>不過另一個角度來看，Unit Test可以當作"範例"，測試過程其實也就是說明程式是如何運作，可以讓其他人容易瞭解你的流程，另外就是遇到一些重複性很高的測試等等。</p>
<p>不過可能是還沒親身搭配專案使用過，目前對於Unit Test實用性還是一知半解，看不到他深處的美好，就像尚未接觸樣板概念前，完全不瞭解他的實用度，直到實際試用過後，才能深深瞭解重要，不過依照目前接觸專案的等級，好像還用不到Unit Test，有機會 .... 再來用看看吧，因為 『<strong>小案子就放它一馬吧</strong>』！！！！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1748/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[閒聊] Unit testing 與其他 testing 的延伸閱讀心得</title>
		<link>http://blog.wabow.com/archives/1723</link>
		<comments>http://blog.wabow.com/archives/1723#comments</comments>
		<pubDate>Thu, 16 Jul 2009 04:57:12 +0000</pubDate>
		<dc:creator>suzy</dc:creator>
				<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1723</guid>
		<description><![CDATA[定義？目的？ 使用時機與決擇？ Testing 的定義 大學時有學了一點皮毛, 大概知道 什麼叫 White-box testing 跟 Black-box testing White-box testing 通常是以程式師的角度, 在懂得程式架構下的測試 Black-box testing 通常是以使用者的角度, 在不知道葫蘆裡裝什麼藥的情況下的測試 這裡還有好多好多種的測試定義唷: Software testing Hardware testing 與 Web Development 有關的: Sandbox testing 就像我們的測試機. Web testing 是在指測試大流量下才會出現的bug 及 硬體效能問題 Ad hoc testing 無章法亂測, 也是一種測法!! Usability testing 可用性測試 - 要考慮 Performance(效能), Accuracy(準確), Recall(回傳), Emotional response(情緒反應) .. 我記得以前學校有一門課叫 Human-computer [...]]]></description>
			<content:encoded><![CDATA[<p>定義？目的？<br />
使用時機與決擇？<br />
<span id="more-1723"></span></p>
<h2>Testing 的定義</h2>
<p>大學時有學了一點皮毛, 大概知道 什麼叫 <a href="http://en.wikipedia.org/wiki/White-box_testing">White-box testing</a> 跟 <a href="http://en.wikipedia.org/wiki/Black-box_testing">Black-box testing</a></p>
<ul>
<li>White-box testing 通常是以程式師的角度, 在懂得程式架構下的測試</li>
<li>Black-box testing 通常是以使用者的角度, 在不知道葫蘆裡裝什麼藥的情況下的測試</li>
</ul>
<p>這裡還有好多好多種的測試定義唷:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Category:Software_testing">Software testing</a></li>
<li><a href="http://en.wikipedia.org/wiki/Category:Hardware_testing">Hardware testing</a></li>
</ul>
<p>與 Web Development 有關的:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Sandbox_%28software_development%29">Sandbox testing</a> 就像我們的測試機.</li>
<li><a href="http://en.wikipedia.org/wiki/Web_testing">Web testing</a> 是在指測試大流量下才會出現的bug 及 硬體效能問題</li>
<li><a href="http://en.wikipedia.org/wiki/Ad_hoc_testing">Ad hoc testing</a> 無章法亂測, 也是一種測法!!</li>
<li><a href="http://en.wikipedia.org/wiki/Usability_testing">Usability testing</a> 可用性測試 - 要考慮 Performance(效能), Accuracy(準確), Recall(回傳), Emotional response(情緒反應) .. 我記得以前學校有一門課叫 Human-computer Interaction 就是在講這個, 也是 <span style="color: #ff0000;">Fail </span>很多人的一門課 因為很難 哈哈哈哈</li>
<li><a href="http://en.wikipedia.org/wiki/Localization_testing">Localization testing</a> 在地化測試</li>
</ul>
<h2>Unit testing 存在的目的</h2>
<p>提昇程式穩定度，帶著更清晰的腦袋瓜寫程式</p>
<p>那麼 Unit testing - 我想把它解讀成它是一種寫 testing 的方法/模式</p>
<p>而 <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test-driven development</a> 就是先寫測試 再寫程式 的一種 Software Design Mode?</p>
<p>TDD 標榜的是先寫好測試的 cases 再開始寫程式. 寫 code 時就比較不會造成程式的漏洞.</p>
<p>我想到一句對我還滿受用的一段至理名言:<br />
<span style="color: #0000ff;"><em><br />
能夠迅速想到解法的程式設計師太多了。<br />
他們能用一分鐘想到方法，用一天去寫程式。<br />
不需要花一小時想到解法，再用一小時去寫程式。<br />
- Jon Bentley</em></span></p>
<p>TDD 某種程度上應該也是這個意思吧! -- 多花點時間準備 before writing.</p>
<p>而有 Unit testing 就有 <a href="http://en.wikipedia.org/wiki/Integration_testing">Integration testing 整合測試</a> -<br />
Unit testing --&gt; Integration testing --&gt; System testing (Black-box)</p>
<h2>Unit testing 實際應用(我目前想得到的)</h2>
<p>其實就是一些很容易算錯的東西..........</p>
<ul>
<li>匯率</li>
<li>運費計算</li>
<li>所有功能都寫在一起的購物車</li>
<li>商業應用..eg 租露營車的估價, <span style="color: #ff0000;"><strong>牛的乳腺炎線上計算</strong></span>(我真的做過! 超難寫的! 這個超需要 Unit testing, 還有 Integration testing !!!)</li>
</ul>
<h2>Unit testing 很難達到實際功效的困難點</h2>
<p>1. 程式師本身的盲點, 搞不好寫了測試但是 bug 還是在 *_*<br />
2. 客戶會改變需求, 有沒有寫了又改, 改了又寫的八卦</p>
<p><span style="color: #0000ff;">我又想到一段至理名言:<br />
<em>需求規格在程式寫完後才會敲定。<br />
基本規格要客戶看到成品後才會決定。<br />
詳細規格要使用者用過後才會確定。</em></span></p>
<p>3. 與時間賽跑, 有時間寫再說<br />
4. 測不到的地方 - 視覺沒有辦法測，調 css 排版沒有辦法測，Ajax 操作也很難完全模仿人的習慣，還有 BROWSER 的問題。</p>
<h2>結論</h2>
<p>Testing 其實很複雜, 應該也只有巨大案子才需要吧.<br />
真的要做的話, 應該還包括各種 case 的分析, 連鎖反應, 如何將各種 testing 運用得宜, 還有流程控制, 可能要畫一堆的 UML Diagram, 還有預演替代方案<br />
應該不是三言兩語就可以說得完的 @o@<br />
而我們的 Web 開發所需要牽涉到的 testing 技術可以到什麼程度其實我也不知道</p>
<p>其實這篇淺薄的心得自己寫得很不好意思, 因為沒有接觸很多, 請大家隨便看看ㄚ, 真的要循續漸進且觀念正確地瞭解透徹, 我覺得可能還是要向<span style="color: #ff0000;"><strong>學術界</strong></span>取經吧 ^^" (逃)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1723/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[哇寶講堂] PHPUnit入門</title>
		<link>http://blog.wabow.com/archives/1704</link>
		<comments>http://blog.wabow.com/archives/1704#comments</comments>
		<pubDate>Wed, 15 Jul 2009 08:30:49 +0000</pubDate>
		<dc:creator>ingrid</dc:creator>
				<category><![CDATA[教育訓練]]></category>
		<category><![CDATA[軟體測試]]></category>

		<guid isPermaLink="false">http://blog.wabow.com/?p=1704</guid>
		<description><![CDATA[哇寶"又"要對外開課囉~歡迎大家一起來分享.討論！！ 課程主題：PHPUnit 入門 身為一個工程師的你一直把時間花在 Debug 嗎？ 為什麼就不能有一個值得信賴的方式，幫助我們驗證我們的程式碼是正確的呢？ 當然有！那就是單元測試！！ 一般人在用 PHP 開發 Web 時，一直很少注意到單元測試這件事， 現在，該是大家去瞭解它的時候了！ 來吧！一切就在 PHPUnit 裡，等著你們來發掘~ 上什麼？       一、單元測試是什麼？       二、單元測試的相關概念       三、PHPUnit 基礎特色介紹       四、問與答       (註：時間來得及的話，會讓大家一起練習 TDD 開發) 誰來上？      朱建志 (Jace Ju)      職稱：哇寶國際資訊技術總監      外號：大澤木小鐵      興趣：分享技術研究心得 適合誰？      - 對 PHP 開發已有兩年以上經驗。      - 對物件導向有基本認知。      - 對程式碼自我要求甚高。      [...]]]></description>
			<content:encoded><![CDATA[<p>哇寶"又"要對外開課囉~歡迎大家一起來分享.討論！！</p>
<h2>課程主題：<span style="color: #333399;">PHPUnit 入門</span></h2>
<p><span style="color: #333399;">身為一個工程師的你一直把時間花在 Debug 嗎？<br />
為什麼就不能有一個值得信賴的方式，幫助我們驗證我們的程式碼是正確的呢？<br />
當然有！那就是單元測試！！</span></p>
<p><span style="color: #333399;">一般人在用 PHP 開發 Web 時，一直很少注意到單元測試這件事，<br />
現在，該是大家去瞭解它的時候了！</span></p>
<p><span style="color: #333399;">來吧！一切就在 PHPUnit 裡，等著你們來發掘~</span></p>
<p><span style="color: #333399;"><br />
</span><span id="more-1704"></span><strong><span style="text-decoration: underline;"><br />
上什麼？</span></strong><br />
      一、單元測試是什麼？<br />
      二、單元測試的相關概念<br />
      三、PHPUnit 基礎特色介紹<br />
      四、問與答<br />
    <span style="color: #888888;">  (註：時間來得及的話，會讓大家一起練習 TDD 開發)</span></p>
<p><strong><span style="text-decoration: underline;"><br />
誰來上？</span></strong><br />
     朱建志 (Jace Ju)<br />
     職稱：哇寶國際資訊技術總監<br />
     外號：大澤木小鐵<br />
     興趣：分享技術研究心得</p>
<p><strong><span style="text-decoration: underline;"><br />
適合誰？</span></strong><br />
     - 對 PHP 開發已有兩年以上經驗。<br />
     - 對物件導向有基本認知。<br />
     - 對程式碼自我要求甚高。<br />
     - 對學習新技術有興趣。</p>
<p><span style="text-decoration: underline;"><strong><br />
何時上？<br />
</strong></span>     <span style="color: #ff0000;">98 年 7 月 24 日(五)  PM2：30 ~ PM4：30</span></p>
<p><span style="color: #000000;"><strong><span style="text-decoration: underline;"><br />
在哪裡？</span></strong><span style="color: #ff0000;"><br />
     GozCafe 果子咖啡</span><br />
     地址：台北市民生東路三段 140 巷 11 號<br />
                <span style="color: #999999;">(捷運南京東路站下，直走慶城街，左轉興安街) </span><br />
     電話：02-8770-533</span></p>
<p><strong><span style="text-decoration: underline;"><br />
課程費用？<br />
</span></strong>      <span style="color: #ff0000;">不需課程費用，但需自行負擔果子咖啡午茶低消費用 100 元。<br />
</span>      午茶內容：精緻午茶茶點(飲料限點 100 元以下) + 一份果子每日茶點<br />
                         <span style="color: #999999;">(也可依個人喜好自行選擇其他餐點，價格依餐點內容而定)<br />
</span>      ※ 備註：入場前請先至櫃檯點餐結帳，謝謝！※</p>
<p><strong><span style="text-decoration: underline;"><br />
人數限制？<br />
</span></strong>      本次課程力求溫馨與實用走向，上課人數<span style="text-decoration: underline;">限 20 人以內</span>，<br />
      有興趣的人請及早報名，以免向隅喔！</p>
<p><strong><span style="text-decoration: underline;"><br />
報名方式？<br />
</span></strong>      有興趣的朋友麻煩請至~ <a href="http://registrano.com/events/phpunit-basic">http://registrano.com/events/phpunit-basic</a> 進行報名！</p>
<p><span style="text-decoration: underline;"><strong><br />
主辦單位：</strong></span><br />
      哇寶國際資訊股份有限公司</p>
<p><span style="color: #ff0000;"><span style="color: #000000;"> </span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wabow.com/archives/1704/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
