產(chǎn)品經(jīng)理 的職責(zé)是探索產(chǎn)品的價(jià)值與挖掘需求并分析可用性、可行性,然后聯(lián)合交互設(shè)計(jì)與技術(shù)開發(fā)人員,共同定義產(chǎn)品的特性并將他實(shí)現(xiàn)。在此過程中,產(chǎn)品經(jīng)理作為中間樞紐,需要和團(tuán)隊(duì)成員進(jìn)行溝通合作,驅(qū)動(dòng)團(tuán)隊(duì)執(zhí)行力與提升
工作 效率。那么如何成為好的產(chǎn)品經(jīng)理呢???
以前我說過:“只要肯用心,每個(gè)人都可以成為產(chǎn)品經(jīng)理!做一名成功的產(chǎn)品經(jīng)理很容易,只是做一名成功產(chǎn)品的產(chǎn)品經(jīng)理不容易! ”因此,在成功之前我們先要成為一名出色的產(chǎn)品經(jīng)理。
下面我將以步驟拆分,一步一步講講如果成為出色的產(chǎn)品經(jīng)理。
一、想成為產(chǎn)品經(jīng)理
首先我們通過某個(gè)途經(jīng)了解到產(chǎn)品經(jīng)理這個(gè)職位,當(dāng)我們深入了解后開始堅(jiān)定自己要成為一名產(chǎn)品經(jīng)理。此時(shí)我們就需要了解成為一名產(chǎn)品經(jīng)理需要哪些準(zhǔn)備。下面我就介紹介紹成為產(chǎn)品經(jīng)理的準(zhǔn)備,這些準(zhǔn)備大多來自于企業(yè)對(duì)應(yīng)聘崗位的要求,但是我們自己也需要對(duì)自身有所要求。
1、人品
人品這個(gè)詞是套用了網(wǎng)絡(luò)詞語,真正含意是個(gè)人素質(zhì)和態(tài)度。產(chǎn)品經(jīng)理在公司是一個(gè)處在中間位置的圓滑角色,因此產(chǎn)品經(jīng)理的素質(zhì)和態(tài)度非常重要。經(jīng)驗(yàn)不足可以積累,知識(shí)不全可以
學(xué)習(xí) ,但是素質(zhì)和態(tài)度是長(zhǎng)期形成的人性習(xí)慣,很難改變,因此企業(yè)招聘對(duì)于這一條非常重視,我們自己也要時(shí)刻反省并提升自己。
2、興趣
正如我開頭所說的,作為一名產(chǎn)品經(jīng)理必須要熱愛這份職業(yè),因此我們必須要對(duì)產(chǎn)品有足夠的興趣。無論是產(chǎn)品經(jīng)理還是其他職業(yè)都一樣,將自己的興趣轉(zhuǎn)化成職業(yè)是最佳的選擇,當(dāng)我們有興趣并熱愛這份職業(yè)時(shí),才能調(diào)動(dòng)出最大的激情,也能在工作中享受到這份喜悅。
在這里我說一句題外話:每一個(gè)團(tuán)隊(duì)都有或多或少的毛病,竟然你選擇了這份職業(yè),選擇了這個(gè)團(tuán)隊(duì),那么請(qǐng)不要輕易放棄。
3、產(chǎn)品思維
不知道你有沒有關(guān)注過產(chǎn)品經(jīng)理的微博,在他們的微博里,你總能看到他們?cè)?a target="_self" style="word-break: break-all; color: #202859; line-height: normal !important;">生活 中對(duì)各種各樣的產(chǎn)品提出各種各樣的建議。在產(chǎn)品人的眼里,一切事物都是產(chǎn)品;產(chǎn)品人的思維總是在不自覺的情況下挑刺,這并非指產(chǎn)品人都是另類潔癖,而是產(chǎn)品人的思維總是以用戶體驗(yàn)的角色對(duì)產(chǎn)品提出體驗(yàn)上的缺陷。產(chǎn)品思維就是一種換位思考的思維,以用戶的視角,融入到產(chǎn)品中并挑出產(chǎn)品設(shè)計(jì)的缺陷。這是一個(gè)可以積累的思維方式,但是在成為產(chǎn)品經(jīng)理之前我們需要有這方面的意識(shí)。
4、邏輯思維
這是一個(gè)非常重要的必備條件,產(chǎn)品經(jīng)理的工作不僅僅是勤奮就足夠的,在產(chǎn)品設(shè)計(jì)中,有很多細(xì)節(jié)問題包含各式各樣的邏輯問題,我們需要理清之間的關(guān)聯(lián),寫出或者畫出可行的產(chǎn)品執(zhí)行方案。我們還需要具有邏輯分拆、組合、混合的思維能力,在產(chǎn)品人的思維里,任何問題都沒有唯一的答案,一項(xiàng)功能總能有多種實(shí)現(xiàn)方案,我們需要清晰的理解并選出最佳的方案。
5、信心
有一種信心叫自信,而這種自信的解釋就是:“眼睛尚未看見就相信,其最終的回報(bào)就是你真正看見了。”我以前在“PM面試中需要注意的事項(xiàng)”
文章 中有說過,產(chǎn)品經(jīng)理是一個(gè)務(wù)實(shí)的職業(yè),千萬不要在團(tuán)隊(duì)成員面前浮夸產(chǎn)品,我們需要寄于數(shù)據(jù)說話(雖然很多時(shí)候數(shù)據(jù)不一定準(zhǔn)確,但是產(chǎn)品經(jīng)理的言論需要有依據(jù)。)。
這里我所指的信心是來自內(nèi)心的自信,我們需要相信自己能夠做好產(chǎn)品經(jīng)理,并且從內(nèi)心散發(fā)出自信的氣息,感染團(tuán)隊(duì)里每一個(gè)人,從而調(diào)動(dòng)大家的積極性。
二、成為產(chǎn)品經(jīng)理之前
當(dāng)我們做好成為產(chǎn)品經(jīng)理的準(zhǔn)備的時(shí)候,下一步我們就需要知道產(chǎn)品經(jīng)理的工作性質(zhì),而這些性質(zhì)是我們對(duì)自身的一種要求,更多的動(dòng)力來自于我們對(duì)這份職業(yè)的熱愛。
1、工作時(shí)間
產(chǎn)品經(jīng)理的工作絕對(duì)不是朝九晚五類型的,一位出色的產(chǎn)品經(jīng)理也絕對(duì)不是朝九晚五的工作,這也就是我前面說到的,我們需要對(duì)這份職業(yè)有濃厚的興趣,只有當(dāng)我們有興趣和熱愛這份職業(yè)才能有動(dòng)力做好產(chǎn)品經(jīng)理。產(chǎn)品就像產(chǎn)品經(jīng)理的孩子,產(chǎn)品經(jīng)理需要對(duì)這個(gè)孩子的前途和命運(yùn)負(fù)責(zé),因此產(chǎn)品經(jīng)理的工作無法用時(shí)間來衡量,在工作之余我們也無法將產(chǎn)品拋諸腦后。
2、工作態(tài)度
以職業(yè)劃分,產(chǎn)品經(jīng)理是一個(gè)光桿司令,沒有直接的職權(quán)管理團(tuán)隊(duì)成員,更不能要求團(tuán)隊(duì)成員執(zhí)行命令。產(chǎn)品經(jīng)理的工作職責(zé)是與多部門溝通合作,通過說服力促使大家通力合作,因此良好的態(tài)度有助于提升團(tuán)隊(duì)工作效率,親和的溝通方式有助于保證工作的質(zhì)量。
3、掌握技術(shù)
雖然產(chǎn)品經(jīng)理不是直接操作技術(shù)的人,但是至少需要了解技術(shù)的實(shí)現(xiàn)原理,這里所指的技術(shù)不僅僅是程序,也包括交互設(shè)計(jì)。有部分企業(yè)會(huì)看重產(chǎn)品經(jīng)理對(duì)技術(shù)的了解,但是很多企業(yè)相信這不重要,因?yàn)榧夹g(shù)原理的學(xué)習(xí)很快,所以在入職前這不是必備的條件。
三、成為產(chǎn)品經(jīng)理
當(dāng)我們正式成為一名產(chǎn)品經(jīng)理的時(shí)候,并不代表我們是一名出色的產(chǎn)品經(jīng)理,下面我再說說產(chǎn)品經(jīng)理在工作當(dāng)中需要具備的能力。
1、善于挖掘性的思考
發(fā)現(xiàn)一個(gè)點(diǎn),先邏輯分類,再邏輯串聯(lián),最后再數(shù)據(jù)挖掘,突現(xiàn)出產(chǎn)品價(jià)值,這就是產(chǎn)品的孵化過程! 產(chǎn)品經(jīng)理的職責(zé)就是探索產(chǎn)品的價(jià)值與挖掘需求并分析可用性、可行性。
2、需求管理
在工作中我們會(huì)不斷的收到需求,這些需求有來自領(lǐng)導(dǎo)、團(tuán)隊(duì)成員、用戶、自己,我們需要對(duì)這些需求進(jìn)行整合并分析可用性、可行性,在確定可行的情況下還需要進(jìn)一步規(guī)劃他的實(shí)施,而實(shí)施之前我們需要通過文檔或者原型做用例推演,推演得出邏輯可行,下一步再高保真的效果演示,最終才能實(shí)施。工作中最忌缺失需求管理,不能收到需求直接給技術(shù)人員實(shí)施,也不能經(jīng)常變更需求。
3、理解用戶體驗(yàn)設(shè)計(jì)
有些企業(yè)會(huì)有獨(dú)門負(fù)責(zé)用戶體驗(yàn)研究的人員,這些人員被稱為用戶研究,他們與產(chǎn)品經(jīng)理、交互設(shè)計(jì)、視覺設(shè)計(jì)共同完成產(chǎn)品原型設(shè)計(jì)和高保真模型設(shè)計(jì)。也有企業(yè)沒有這樣的人員,而此時(shí)通常需要產(chǎn)品經(jīng)理自己理解用戶體驗(yàn)設(shè)計(jì),與設(shè)計(jì)師共同完成原型設(shè)計(jì)。
4、時(shí)間管理
無論什么職業(yè),時(shí)間管理尤其重要,時(shí)間管理也叫日程管理,是我們?nèi)粘9ぷ靼才诺墓芾恚侠淼臅r(shí)間管理可以幫我們明確輕重緩急,提升工作效率。下面四種等級(jí)是很多企業(yè)常用的工作優(yōu)先級(jí)的排序規(guī)則。
重要(緊急)
重要(不緊急)
不重要(緊急)
不重要(不緊急)
5、化解壓力與矛盾
產(chǎn)品經(jīng)理是團(tuán)隊(duì)的樞紐點(diǎn),也是壓力、矛盾的集中營(yíng),所以我們自己需要有一個(gè)良性的化解壓力的方法,在解決自身壓力的同時(shí)還要化解團(tuán)隊(duì)的矛盾。
解壓的方法每個(gè)人都有不同,但是化解矛盾都是大同小異的。首先我們需要先知道矛盾往往先是從抱怨與指責(zé)開始的,我們?cè)谔幚肀г古c指責(zé)的時(shí)候需要清楚,這是一個(gè)毒瘤,會(huì)越長(zhǎng)越大,最終會(huì)直接影響團(tuán)隊(duì)的和諧,所以我們必須要制止它的發(fā)展,避免大家陷入這樣的慣性旋窩中。
抱怨與指責(zé)是雙向的,別人可以迷失,但是我們作為產(chǎn)品經(jīng)理必須要保持理性,結(jié)束抱怨與指責(zé),主動(dòng)道歉,終止抱怨與指責(zé)不斷的擴(kuò)大,那怕不是我們的錯(cuò),但是我們是產(chǎn)品經(jīng)理,終止毒瘤的發(fā)展是我們的職責(zé),等待大家保持冷靜后再溝通。
因此產(chǎn)品經(jīng)理需要時(shí)刻保持理性,并且減少抱怨與指責(zé),更不能為自己找借口,必須克服所有障礙,解決所有問題。
四、成為出色的產(chǎn)品經(jīng)理
一名出色的產(chǎn)品經(jīng)理必然有著這樣的頭銜:執(zhí)行力驅(qū)動(dòng)者、工作效率提升者、團(tuán)隊(duì)合作促進(jìn)者。
1、明確工作職責(zé)和目標(biāo)
首先我們需要知道三個(gè)問題的答案:工作職責(zé)、工作目標(biāo)、工作方向。
1.1、產(chǎn)品經(jīng)理的工作職責(zé)就是探索產(chǎn)品的價(jià)值與挖掘需求并分析可用性、可行性。
1.2、產(chǎn)品經(jīng)理的工作目標(biāo)就是在最短的時(shí)間內(nèi)理清產(chǎn)品需求,確定產(chǎn)品的邏輯關(guān)系。
1.3、產(chǎn)品經(jīng)理的工作方向就是不斷提升產(chǎn)品的價(jià)值。
2、了解團(tuán)隊(duì)成員的職責(zé)
在團(tuán)隊(duì)中有三個(gè)部門最為密切關(guān)聯(lián),分別是產(chǎn)品部、設(shè)計(jì)部、技術(shù)部。產(chǎn)品負(fù)責(zé)多方協(xié)調(diào),設(shè)計(jì)往往有交互設(shè)計(jì)與視覺設(shè)計(jì)兩種,統(tǒng)稱用戶體驗(yàn)設(shè)計(jì),在設(shè)計(jì)人員的腦子里,更多的想的是美觀風(fēng)格。在團(tuán)隊(duì)當(dāng)中,與技術(shù)人員的溝通最為吃力,所以我們更加需要了解技術(shù)人員的想法。技術(shù)人員往往不擅長(zhǎng)用戶體驗(yàn)設(shè)計(jì),因?yàn)榧夹g(shù)人員的腦子里想的是實(shí)現(xiàn)模型,而產(chǎn)品經(jīng)理的腦子里想的是概念模型。
了解團(tuán)隊(duì)成員的職責(zé)和想法,有助于我們協(xié)調(diào)溝通,以他們的思維出發(fā),將產(chǎn)品經(jīng)理腦子里的概念模型寫出來、畫出來、講出來。
3、明確任務(wù)重心和方向
當(dāng)我們分配任務(wù)時(shí),我們同時(shí)需要告訴對(duì)方任務(wù)的目標(biāo)與用途,并且明確完成時(shí)間和優(yōu)先級(jí),這樣有助于提升工作效率。
4、緊密的團(tuán)隊(duì)合作
從產(chǎn)品原型開始,團(tuán)隊(duì)之間就應(yīng)該保持密切的合作,產(chǎn)品經(jīng)理確定產(chǎn)品的需求,明確產(chǎn)品要做什么,然后調(diào)動(dòng)大家積累參與到產(chǎn)品的設(shè)計(jì)當(dāng)中。從設(shè)計(jì)部獲得最佳的用戶體驗(yàn)與交互設(shè)計(jì)方案,從技術(shù)部獲得最新的技術(shù)動(dòng)態(tài),以便分析能否應(yīng)用到產(chǎn)品當(dāng)中。特別與技術(shù)部的合作更為密切,產(chǎn)品經(jīng)理需要了解自己規(guī)劃的產(chǎn)品原型能否實(shí)現(xiàn),從技術(shù)層面能否實(shí)現(xiàn)。
5、不要輕易變更需求
在需求管理中已經(jīng)寫過,特別在產(chǎn)品進(jìn)入開發(fā)階段時(shí),不要輕易變更需求。避免不斷變更需求延誤開發(fā)進(jìn)度,有新需求時(shí)可以考慮在下一個(gè)版本中改進(jìn)。
開發(fā)人員常常使用
單元測(cè)試 來驗(yàn)證的一段兒代碼的操作,很多時(shí)候單元測(cè)試可以檢查拋出預(yù)期異常( expected exceptions)的代碼。在Java語言中,
JUnit 是一套標(biāo)準(zhǔn)的單元測(cè)試方案,它提供了很多驗(yàn)證拋出的異常的機(jī)制。本文就探討一下他們的優(yōu)點(diǎn)。
我們拿下面的代碼作為例子,寫一個(gè)測(cè)試,確保canVote() 方法返回true或者false, 同時(shí)你也能寫一個(gè)測(cè)試用來驗(yàn)證這個(gè)方法拋出的IllegalArgumentException異常。
public class Student {
public boolean canVote(int age) {
if (i<=0) throw new IllegalArgumentException("age should be +ve");
if (i<18) return false;
else return true;
}
}
(Guava類庫中提供了一個(gè)作參數(shù)檢查的工具類--Preconditions類,也許這種方法能夠更好的檢查這樣的參數(shù),不過這個(gè)例子也能夠檢查)。
檢查拋出的異常有三種方式,它們各自都有優(yōu)缺點(diǎn):
1.@Test(expected…)
@Test注解有一個(gè)可選的參數(shù),"expected"允許你設(shè)置一個(gè)Throwable的子類。如果你想要驗(yàn)證上面的canVote()方法拋出預(yù)期的異常,我們可以這樣寫:
@Test(expected = IllegalArgumentException.class)
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
student.canVote(0);
}
簡(jiǎn)單明了,這個(gè)測(cè)試有一點(diǎn)誤差,因?yàn)楫惓?huì)在方法的某個(gè)位置被拋出,但不一定在特定的某行。
2.ExpectedException
如果要使用JUnit框架中的ExpectedException類,需要聲明ExpectedException異常。
@Rule
public ExpectedException thrown= ExpectedException.none();
然后你可以使用更加簡(jiǎn)單的方式驗(yàn)證預(yù)期的異常。
@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
thrown.expect(NullPointerException.class);
student.canVote(0);
}
或者可以設(shè)置預(yù)期異常的屬性信息。
@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("age should be +ve");
student.canVote(0);
}
除了可以設(shè)置異常的屬性信息之外,這種方法還有一個(gè)優(yōu)點(diǎn),它可以更加精確的找到異常拋出的位置。在上面的例子中,在構(gòu)造函數(shù)中拋出的未預(yù)期的(unexpected) IllegalArgumentException 異常將會(huì)引起測(cè)試失敗,我們希望它在canVote()方法中拋出。
從另一個(gè)方面來說,如果不需要聲明就更好了
@Rule
public ExpectedException thrown= ExpectedException.none();
它就像不需要的噪音一樣,如果這樣就很好了
expect(RuntimeException.class)
或者:
expect(RuntimeException.class, “Expected exception message”)
或者至少可以將異常和信息當(dāng)做參數(shù)傳進(jìn)去
thrown.expect(IllegalArgumentException.class, “age should be +ve”);
3.Try/catch with assert/fail
在JUnit4之前的版本中,使用try/catch語句塊檢查異常
@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
try {
student.canVote(0);
} catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("age should be +ve"));
}
fail("expected IllegalArgumentException for non +ve age");
}
盡管這種方式很老了,不過還是非常有效的。主要的缺點(diǎn)就是很容易忘記在catch語句塊之后需要寫fail()方法,如果預(yù)期異常沒有拋出就會(huì)導(dǎo)致信息的誤報(bào)。我曾經(jīng)就犯過這樣的錯(cuò)誤。
總之,這三種方法都可以測(cè)試預(yù)期拋出的異常,各有優(yōu)缺點(diǎn)。對(duì)于我個(gè)人而言,我會(huì)選擇第二種方法,因?yàn)樗梢苑浅>_、高效的測(cè)試異常信息。
English »
Afrikaans Albanian Arabic Armenian Azerbaijani Basque Bengali Belarusian Bulgarian Catalan Chinese (Simp) Chinese (Trad) Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Galician Georgian German Greek Gujarati Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Kannada Korean Lao Latin Latvian Lithuanian Macedonian Malay Maltese Norwegian Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Tamil Telugu Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish
問題
[Simplified Chinese] 使用
IBM Rational AppScan Standard版本對(duì)Web程序進(jìn)行掃描時(shí),如何對(duì)發(fā)生的通信問題進(jìn)行分析?
癥狀
現(xiàn)象 1
在掃描過程中掃描日志(選擇菜單[查看] > [掃描日志]或者從Rational AppScan Standard安裝路徑下的Logs文件夾中打開ScanLog.log文件)可能會(huì)顯示以下格式的錯(cuò)誤消息:
[DATE], [TIME]: Cannot connect to host: [IP/HOSTNAME]...
[DATE], [TIME]:
Test [TEST_NUMBER] [TEST_NAME] failed due to communication error: [PATH]...
[DATE], [TIME]: Connection established with host: [IP/HOSTNAME]
現(xiàn)象 2
或者在AppScan系統(tǒng)日志(選擇菜單[幫助] > [AppScan 日志]或者從Rational AppScan Standard安裝路徑下的Logs文件夾中打開AppScanSys.log文件)中可能會(huì)發(fā)生如下的錯(cuò)誤消息:
[DAY_OF_WEEK], [DATE], [TIME] Warning: Communication problems occurred while testing URL '[PATH]' for '[TEST_NAME]'
同時(shí)也可能看到如下消息:
[DAY_OF_WEEK], [DATE], [TIME] System : Server [IP/HOSTNAME] is not responding...
[DAY_OF_WEEK], [DATE], [TIME] System : Server [IP/HOSTNAME] is responding again
或者如下消息:
[DAY_OF_WEEK], [DATE], [TIME] System : Proxy [IP/HOSTNAME] is not responding
[DAY_OF_WEEK], [DATE], [TIME] System : Proxy [IP/HOSTNAME] is responding again
原因
通常由于以下原因會(huì)導(dǎo)致發(fā)生通信問題:
原因 1
在Rational AppScan Standard的主機(jī)上安裝的個(gè)人防火墻或防病毒軟件會(huì)屏蔽向外發(fā)送的信息。
原因 2
企業(yè)防火墻軟件會(huì)將AppScan發(fā)送的請(qǐng)求當(dāng)作對(duì)網(wǎng)站的攻擊從而切斷連接。
原因 3
當(dāng)Rational AppScan Standard對(duì)于響應(yīng)速度慢的Web服務(wù)器發(fā)送大量的請(qǐng)求時(shí),請(qǐng)求會(huì)被服務(wù)器拒絕。
解決問題
原因1的解決方案:
在探索和
測(cè)試 的階段需要確保此類軟件已經(jīng)停止運(yùn)行。
原因2的解決方案:
在系統(tǒng)管理員的協(xié)助下需要確認(rèn)企業(yè)防火墻是否真正切斷AppScan的連接。通常當(dāng)網(wǎng)絡(luò)中安裝了新的代理服務(wù)器或防火墻時(shí),會(huì)屏蔽請(qǐng)求從而降低Rational AppScan Standard的
工作 效率。
原因3的解決方案:
1.在[掃描配置] > [通信和代理]中,將[線程數(shù)]降為1同時(shí)將[超時(shí)]增大為30秒。如果能夠消除通信錯(cuò)誤消息的話,可以少量增加線程的數(shù)目。
2.可以設(shè)定Rational AppScan Standard使用HTTP/1.1來解決通信問題。關(guān)于設(shè)定AppScan使用HTTP/1.1更多的內(nèi)容,請(qǐng)參照Technote 1298662: Forcing Rational AppScan Standard to use HTTP/1.1。
English »
Afrikaans Albanian Arabic Armenian Azerbaijani Basque Bengali Belarusian Bulgarian Catalan Chinese (Simp) Chinese (Trad) Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Galician Georgian German Greek Gujarati Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Kannada Korean Lao Latin Latvian Lithuanian Macedonian Malay Maltese Norwegian Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Tamil Telugu Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish
作者認(rèn)為這是最具爭(zhēng)議的項(xiàng)目, 他認(rèn)為這是一個(gè)神話: "
測(cè)試 人員只需要一點(diǎn), 或是沒有程序撰寫的知識(shí)". 這是行不通的, 可是很不幸的, 這是目前一般常見的狀況. 這里作者提出兩個(gè)主要原因
(1) 測(cè)試人員是在測(cè)試軟件程序, 沒有程序設(shè)計(jì)的知識(shí), 他們無法洞察bugs真正的原因, 找出最可能發(fā)生問題的地方. 測(cè)試通常沒有足夠的時(shí)間, 去達(dá)到真正測(cè)試的"完整", 所以
軟件測(cè)試 是需要在現(xiàn)有資源和徹底性之間做出某種妥協(xié). 測(cè)試人員要如何優(yōu)化有限的資源, 針對(duì)最可能發(fā)生問題的地方做測(cè)試呢? 如果他沒有程序設(shè)計(jì)的知識(shí), 他不可能有正確的直覺, 去知道要去哪里找到這些地方
(2) 所有最簡(jiǎn)單的測(cè)試方法都是tool- and technology-intensive. 基本上, 這些工具都是需要程序撰寫或設(shè)計(jì)的知識(shí), 才知道怎樣用的好. 同理, testing techniques也是一樣. 若是你沒這些知識(shí), 你可能只能用一些ad hoc的testing techniques和最簡(jiǎn)單的工具
此外作者還認(rèn)為找entry level的程序設(shè)計(jì)人員來當(dāng)測(cè)試人員, 這并不是好的主意. 原因如下:
(1) 失敗者的形象 (Loser Image)
Entry-level的人會(huì)期待得到一個(gè)開發(fā)人員的
工作 , 如果他們不能找到這樣的職位, 他們會(huì)覺得是一種失敗. 這種情況在測(cè)試團(tuán)隊(duì)會(huì)更明顯
(2) 開發(fā)人員對(duì)你沒有信任感 (Credibility With Programmers)
測(cè)試人員所面對(duì)的開發(fā)人員往往比他們資深很多, 除非他們之前所學(xué)的東西十分扎實(shí), 否則他們所會(huì)的東西, 在開發(fā)人員面前會(huì)只是玩具而已. 因此他們沒有什么公信力, 去提供開發(fā)人員什么有用的信息.
(3) 測(cè)試人員不懂訣竅(Just Plain Know-How)
基本上, 這些測(cè)試人員不懂程序?qū)嶋H上怎么撰寫, 那是開發(fā)人員的本業(yè). 如果你是開發(fā)人員, 資深的人還會(huì)去帶剛?cè)腴T的人怎么做. 若是你是測(cè)試人員, 你只會(huì)去學(xué) doing a build, configuration control, procedures, process等等. 都是在
學(xué)習(xí) 怎么做, 而不是真正去做它. 所以無法真正懂得那些訣竅
English »
Afrikaans Albanian Arabic Armenian Azerbaijani Basque Bengali Belarusian Bulgarian Catalan Chinese (Simp) Chinese (Trad) Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Galician Georgian German Greek Gujarati Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Kannada Korean Lao Latin Latvian Lithuanian Macedonian Malay Maltese Norwegian Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Tamil Telugu Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish
首先說介紹一下,Assert類所在的命名空間為Microsoft.VisualStudio.TestTools.UnitTesting 在工程文件中只要引用Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll就可以使用了,在這里我舉例說明Assert里面的一些主要的靜態(tài)成員。
1、 AreEqual:方法被重載了N多次,主要功能是判斷兩個(gè)值是否相等;如果兩個(gè)值不相等,則
測(cè)試 失敗。
2、 AreNotEqual:方法被重載了N多次,主要功能是判斷兩個(gè)值是否不相等;如果兩個(gè)值相等,則測(cè)試失敗。
3、 AreNotSame:引用的對(duì)象是否不相同;如果兩個(gè)輸入內(nèi)容引用相同的對(duì)象,則測(cè)試失敗.
4、 AreSame:引用的對(duì)象是否相同;如果兩個(gè)輸入內(nèi)容引用不相同的對(duì)象,則測(cè)試失敗.
5、 Fail:斷言失敗。
6、 Inconclusive:表示無法證明為 true 或 false 的測(cè)試結(jié)果
7、 IsFalse:指定的條件是否為 false;如果該條件為 true,則測(cè)試失敗。
8、 IsTrue:指定的條件是否為 true;如果該條件為 false,則測(cè)試失敗
9、 IsInstanceofType:測(cè)試指定的對(duì)象是否為所需類型的實(shí)例;如果所需的實(shí)例不在該對(duì)象的繼承層次結(jié)構(gòu)中,則測(cè)試失敗
10、IsNotInstanceofType: 測(cè)試指定的對(duì)象是否為所需類型的實(shí)例;如果所需的實(shí)例在該對(duì)象的繼承層次結(jié)構(gòu)中,則測(cè)試失敗
11、IsNull:測(cè)試指定的對(duì)象是否為非空
12、IsNotNull:測(cè)試指定的對(duì)象是否為非空
English »
Afrikaans Albanian Arabic Armenian Azerbaijani Basque Bengali Belarusian Bulgarian Catalan Chinese (Simp) Chinese (Trad) Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Galician Georgian German Greek Gujarati Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Kannada Korean Lao Latin Latvian Lithuanian Macedonian Malay Maltese Norwegian Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Tamil Telugu Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish
Text-to-speech function is limited to 100 characters
soapUI Pro指標(biāo)項(xiàng)說明:
Sets the startup delay for each thread (in milliseconds), setting to 0 will start all threads simultaneously.
min
The shortest time the step has taken (in milliseconds).
max
The longest time the step has taken (in milliseconds).
avg
The average time for the test step (in milliseconds).
last
The last time for the test step (in milliseconds).
cnt
The number of times the test step has been executed.
tps
The number of transactions per second for the test step, see Calculation of TPS/BPS below.
bytes
The number of bytes processed by the test step.
bps
The bytes per second processed by the test step.
err
The number of assertion errors for the test step.
rat
Failed requests ratio (the percentage of requests that failed).
1、Test Step:調(diào)用方法名稱。
2、min、max、avg、last:調(diào)用時(shí)的最小、最大、平均、最近一次的響應(yīng)時(shí)間
3、cnt總調(diào)用次數(shù) ;tps平均每秒調(diào)用次數(shù)
4、bytes接口處理的字符數(shù);bps平均每秒接口處理的字符數(shù)
5、err報(bào)錯(cuò)次數(shù);rat報(bào)錯(cuò)次數(shù)/執(zhí)行次數(shù)
或
min,最小響應(yīng)時(shí)間
max,最大響應(yīng)時(shí)間
avg,平均響應(yīng)時(shí)間
last,上一次請(qǐng)求響應(yīng)時(shí)間
cnt,請(qǐng)求數(shù)
tps,每秒處理請(qǐng)求數(shù)
bps,吞吐率
rat,錯(cuò)誤率
為了
測(cè)試 這個(gè)存儲(chǔ)過程,我遙了一圈去做這個(gè)事情,這里說一下我自己接受到任務(wù)和自己開始是怎么想的。
方法一:
一開始我想著可以使用C#直接去調(diào)用存儲(chǔ)過程,然后用
Loadrunner 調(diào)用C#的dll去測(cè)試,后來發(fā)現(xiàn)找不到LoadRunner怎樣直接調(diào)用C#寫的dll;可是dll存儲(chǔ)過程都已經(jīng)寫好,不可能推倒重新用其他的方式去做,由于任務(wù)時(shí)間比較緊,就山寨的用C#寫了個(gè) .exe 去調(diào)用 dll,完成后執(zhí)行,印象是:
數(shù)據(jù)庫 跟本一點(diǎn)壓力都沒有,可是負(fù)載機(jī)都已經(jīng) 100%了,并且這種做法得需要在每臺(tái)負(fù)載機(jī)都安裝一個(gè)
oracle 客戶端,要不訪問不了,負(fù)載機(jī)有 30臺(tái),每臺(tái)都去安裝一編,我倒!
方法二:
最后想到一種方法,寫一個(gè)WebService 去調(diào)用Dll,Loadrunner再去調(diào)用WebService去進(jìn)行測(cè)試。(這種做法是不是很笨?有沒有其他更好的方法,請(qǐng)留言給我!)
下面就把整個(gè)過程詳細(xì)列一下,其實(shí)這個(gè)之前也都有做過,但由于沒有記錄到博客,全忘記了,重寫是多么的痛苦,血的教訓(xùn)說明:寫博客還是有必需的!
Step1:編寫訪問存儲(chǔ)過程的dll
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Linq;
using System.Text;
namespace PaysysInterfaceTest
{
public class PaysysBase
{
public OracleConnection conn = null;
public OracleCommand cmd = null;
/// <summary>
/// 數(shù)據(jù)庫初始化
/// </summary>
/// <param name="DataSource">數(shù)據(jù)庫源(Orlacle Client下的tnsnames.ora配置</param>
/// <param name="DataUserId">數(shù)據(jù)庫登錄名</param>
/// <param name="DataPassword">數(shù)據(jù)庫登錄密碼</param>
/// <returns></returns>
public int PaysysInit(string DataSource, string DataUserId, string DataPassword)
{
var mConn = string.Format("Data Source={0};User Id={1};Password={2};", DataSource, DataUserId, DataPassword);
conn = new OracleConnection(mConn);
try
{
conn.Open();
cmd = new OracleCommand();
cmd.Connection = conn;
}
catch (Exception ex)
{
return 0;
}
return 1;
}
/// <summary>
/// 調(diào)用的存儲(chǔ)過程
/// </summary>
/// <param name="interfaceName">存儲(chǔ)過程名稱</param>
/// <returns></returns>
public int CallInterface(string interfaceName)
{
var nResult = 0;
var queryString = interfaceName;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = queryString;
try
{
cmd.ExecuteNonQuery();
Console.WriteLine("Query Success!!");
nResult = Convert.ToInt32(cmd.Parameters["result"].Value);
}
catch (Exception ex)
{
Console.WriteLine("Query Error!!\r\n" + ex.Message);
nResult = Convert.ToInt32(cmd.Parameters["result"].Value); ;
}
finally
{
cmd.Clone();
conn.Close();
Console.WriteLine("Close Db");
}
return nResult;
}
}
public class PlayerLogin : PaysysBase
{
public string s_account = "";
public string s_password = "";
/// <summary>
/// 存儲(chǔ)過程初始化參數(shù)
/// </summary>
/// <param name="account">用戶賬號(hào)</param>
/// <param name="password">用戶密碼</param>
public void LoginInit(string account, string password)
{
s_account = account;
s_password = password;
InitParam();
}
/// <summary>
/// 初始化信息
/// </summary>
private void InitParam()
{
//反回值
cmd.Parameters.Add("result", OracleType.Float);
cmd.Parameters["result"].Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("s_account", OracleType.VarChar);
cmd.Parameters["s_account"].Direction = ParameterDirection.Input;
cmd.Parameters["s_account"].Value = s_account;
cmd.Parameters.Add("s_password", OracleType.VarChar);
cmd.Parameters["s_password"].Direction = ParameterDirection.Input;
cmd.Parameters["s_password"].Value = s_password;
//==================out==================
cmd.Parameters.Add("d_login_time", OracleType.DateTime);
cmd.Parameters["d_login_time"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("d_last_login_time", OracleType.DateTime);
cmd.Parameters["d_last_login_time"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("d_last_logout_time", OracleType.DateTime);
cmd.Parameters["d_last_logout_time"].Direction = ParameterDirection.Output;
}
// <summary>
/// 調(diào)用執(zhí)行存儲(chǔ)過程
/// </summary>
/// <returns></returns>
public int LoginInterface()
{
return CallInterface("player.login");
}
}
public class PlayerLogout : PaysysBase
{
public string s_account = "";
public void LogoutInit(string account)
{
s_account = account;
InitParam();
}
private void InitParam()
{
//反回值
cmd.Parameters.Add("result", OracleType.Float);
cmd.Parameters["result"].Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("s_account", OracleType.VarChar);
cmd.Parameters["s_account"].Direction = ParameterDirection.Input;
cmd.Parameters["s_account"].Value = s_account;
}
public int LogoutInterface()
{
return CallInterface("player.logout");
}
}
}
遇到問題:
1、在編寫login的接口時(shí),因?yàn)橹怀跏蓟薎nput的參數(shù),還以為不需要Output的參數(shù),所以導(dǎo)致調(diào)用的時(shí)候一直出現(xiàn)參數(shù)缺少的問題。入?yún)⒑统鰠⒍夹枰睿?/div>
Setp2:WebServices調(diào)用dll
1、新建工程:
2、新建好工程后添加剛剛寫好的dll
3、WebService調(diào)用代碼
[WebMethod]
public string PaysysLogin(string dbName, string dbAccount, string dbPassword, string account, string password)
{
var nResult = 0;
try
{
PlayerLogin login = new PlayerLogin();
login.PaysysInit(dbName, dbAccount, dbPassword);
login.LoginInit(account, password);
nResult = login.LoginInterface();
}
catch (Exception ex)
{
return ex.Message;
}
return nResult.ToString();
}
[WebMethod]
public string PaysysLogout(string dbName, string dbAccount, string dbPassword, string account)
{
var nResult = 0;
try
{
PlayerLogout logout = new PlayerLogout();
logout.PaysysInit(dbName, dbAccount, dbPassword);
logout.LogoutInit(account);
nResult = logout.LogoutInterface();
}
catch (Exception ex)
{
return ex.Message;
}
return nResult.ToString();
}
之后就可以調(diào)試一下了!
Setp3:部署到IIS(可以查看我之前的一編博客,是一樣的)
http://www.cnblogs.com/Martin_Q/archive/2010/12/06/1897614.html
調(diào)試結(jié)果
遇到問題:
這里遇到一個(gè)很糟糕的問題,使用IIS在調(diào)用到:conn.Open() 的時(shí)候出現(xiàn)一個(gè)錯(cuò)誤:system.data.oracleclient 需要 oracle 客戶端軟件 8.1.7 或更高版本。
這個(gè)問題一定要值得注意,開始我以為是iis沒有權(quán)限訪問oracle目錄,我為什么會(huì)這么認(rèn)為呢?因?yàn)槲覟榱瞬檫@個(gè)問題,我專門寫了一個(gè).exe 去執(zhí)行調(diào)用,exe應(yīng)用程序執(zhí)行成功,iis出錯(cuò)!
原來問題是由于我安裝的oracle客戶端為簡(jiǎn)易版本,很多很多的dll都沒有。可以網(wǎng)上找一下:10201_client_win32.zip 些版本client,當(dāng)然還有其他的權(quán)限問題!這里沒遇到就不談了
Setp4:使用LoadRunner調(diào)用WebServices
1、Loadrunner新建WebService
2、點(diǎn)ManageServices 添加你的WebService地址
3、添加WebService 調(diào)用接口
搭建的地址為:http://10.20.87.62:81/Service.asmx 為什么后面需要手工加一個(gè):?WSDL 呢?(知道的同學(xué)說一下!)
4、添加成功
5、添加對(duì)應(yīng)的存儲(chǔ)過程
6、添加成功后Action代碼
Action()
{
lr_start_transaction("Login");
web_service_call( "StepName=PaysysLogin_101",
"SOAPMethod=Service|ServiceSoap|PaysysLogin",
"ResponseParam=response",
"Service=Service",
"ExpectedResponse=SoapResult",
"Snapshot=t1386150115.inf",
BEGIN_ARGUMENTS, // 參數(shù)傳入
"dbName=orcl_35",
"dbAccount=root",
"dbPassword=123456",
"account={Account}",
"password=a",
END_ARGUMENTS,
BEGIN_RESULT, // 獲取返回值
"PaysysLoginResult=LoginResult",
END_RESULT,
LAST);
lr_message("All:%s\r\nLoginResult:%s\r\n",lr_eval_string("{response}"),lr_eval_string("{LoginResult}"));
if(atoi(lr_eval_string("{LoginResult}")) == 1)
{
lr_end_sub_transaction("Login",LR_PASS);
}
else
{
lr_end_sub_transaction("Login",LR_FAIL);
lr_error_message("Login Error:%s ---- %s",lr_eval_string("{LoginResult}"),lr_eval_string("{Account}"));
}
return 0;
}
輸出結(jié)果:
All:<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><PaysysLoginResponse xmlns="http://tempuri.org/"><PaysysLoginResult>1</PaysysLoginResult></PaysysLoginResponse></soap:Body></soap:Envelope>
LoginResult:1
為了
測(cè)試 這個(gè)存儲(chǔ)過程,我遙了一圈去做這個(gè)事情,這里說一下我自己接受到任務(wù)和自己開始是怎么想的。
方法一:
一開始我想著可以使用C#直接去調(diào)用存儲(chǔ)過程,然后用
Loadrunner 調(diào)用C#的dll去測(cè)試,后來發(fā)現(xiàn)找不到LoadRunner怎樣直接調(diào)用C#寫的dll;可是dll存儲(chǔ)過程都已經(jīng)寫好,不可能推倒重新用其他的方式去做,由于任務(wù)時(shí)間比較緊,就山寨的用C#寫了個(gè) .exe 去調(diào)用 dll,完成后執(zhí)行,印象是:
數(shù)據(jù)庫 跟本一點(diǎn)壓力都沒有,可是負(fù)載機(jī)都已經(jīng) 100%了,并且這種做法得需要在每臺(tái)負(fù)載機(jī)都安裝一個(gè)
oracle 客戶端,要不訪問不了,負(fù)載機(jī)有 30臺(tái),每臺(tái)都去安裝一編,我倒!
方法二:
最后想到一種方法,寫一個(gè)WebService 去調(diào)用Dll,Loadrunner再去調(diào)用WebService去進(jìn)行測(cè)試。(這種做法是不是很笨?有沒有其他更好的方法,請(qǐng)留言給我!)
下面就把整個(gè)過程詳細(xì)列一下,其實(shí)這個(gè)之前也都有做過,但由于沒有記錄到博客,全忘記了,重寫是多么的痛苦,血的教訓(xùn)說明:寫博客還是有必需的!
Step1:編寫訪問存儲(chǔ)過程的dll
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Linq;
using System.Text;
namespace PaysysInterfaceTest
{
public class PaysysBase
{
public OracleConnection conn = null;
public OracleCommand cmd = null;
/// <summary>
/// 數(shù)據(jù)庫初始化
/// </summary>
/// <param name="DataSource">數(shù)據(jù)庫源(Orlacle Client下的tnsnames.ora配置</param>
/// <param name="DataUserId">數(shù)據(jù)庫登錄名</param>
/// <param name="DataPassword">數(shù)據(jù)庫登錄密碼</param>
/// <returns></returns>
public int PaysysInit(string DataSource, string DataUserId, string DataPassword)
{
var mConn = string.Format("Data Source={0};User Id={1};Password={2};", DataSource, DataUserId, DataPassword);
conn = new OracleConnection(mConn);
try
{
conn.Open();
cmd = new OracleCommand();
cmd.Connection = conn;
}
catch (Exception ex)
{
return 0;
}
return 1;
}
/// <summary>
/// 調(diào)用的存儲(chǔ)過程
/// </summary>
/// <param name="interfaceName">存儲(chǔ)過程名稱</param>
/// <returns></returns>
public int CallInterface(string interfaceName)
{
var nResult = 0;
var queryString = interfaceName;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = queryString;
try
{
cmd.ExecuteNonQuery();
Console.WriteLine("Query Success!!");
nResult = Convert.ToInt32(cmd.Parameters["result"].Value);
}
catch (Exception ex)
{
Console.WriteLine("Query Error!!\r\n" + ex.Message);
nResult = Convert.ToInt32(cmd.Parameters["result"].Value); ;
}
finally
{
cmd.Clone();
conn.Close();
Console.WriteLine("Close Db");
}
return nResult;
}
}
public class PlayerLogin : PaysysBase
{
public string s_account = "";
public string s_password = "";
/// <summary>
/// 存儲(chǔ)過程初始化參數(shù)
/// </summary>
/// <param name="account">用戶賬號(hào)</param>
/// <param name="password">用戶密碼</param>
public void LoginInit(string account, string password)
{
s_account = account;
s_password = password;
InitParam();
}
/// <summary>
/// 初始化信息
/// </summary>
private void InitParam()
{
//反回值
cmd.Parameters.Add("result", OracleType.Float);
cmd.Parameters["result"].Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("s_account", OracleType.VarChar);
cmd.Parameters["s_account"].Direction = ParameterDirection.Input;
cmd.Parameters["s_account"].Value = s_account;
cmd.Parameters.Add("s_password", OracleType.VarChar);
cmd.Parameters["s_password"].Direction = ParameterDirection.Input;
cmd.Parameters["s_password"].Value = s_password;
//==================out==================
cmd.Parameters.Add("d_login_time", OracleType.DateTime);
cmd.Parameters["d_login_time"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("d_last_login_time", OracleType.DateTime);
cmd.Parameters["d_last_login_time"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("d_last_logout_time", OracleType.DateTime);
cmd.Parameters["d_last_logout_time"].Direction = ParameterDirection.Output;
}
// <summary>
/// 調(diào)用執(zhí)行存儲(chǔ)過程
/// </summary>
/// <returns></returns>
public int LoginInterface()
{
return CallInterface("player.login");
}
}
public class PlayerLogout : PaysysBase
{
public string s_account = "";
public void LogoutInit(string account)
{
s_account = account;
InitParam();
}
private void InitParam()
{
//反回值
cmd.Parameters.Add("result", OracleType.Float);
cmd.Parameters["result"].Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("s_account", OracleType.VarChar);
cmd.Parameters["s_account"].Direction = ParameterDirection.Input;
cmd.Parameters["s_account"].Value = s_account;
}
public int LogoutInterface()
{
return CallInterface("player.logout");
}
}
}
遇到問題:
1、在編寫login的接口時(shí),因?yàn)橹怀跏蓟薎nput的參數(shù),還以為不需要Output的參數(shù),所以導(dǎo)致調(diào)用的時(shí)候一直出現(xiàn)參數(shù)缺少的問題。入?yún)⒑统鰠⒍夹枰睿?/div>
Setp2:WebServices調(diào)用dll
1、新建工程:
2、新建好工程后添加剛剛寫好的dll
3、WebService調(diào)用代碼
[WebMethod]
public string PaysysLogin(string dbName, string dbAccount, string dbPassword, string account, string password)
{
var nResult = 0;
try
{
PlayerLogin login = new PlayerLogin();
login.PaysysInit(dbName, dbAccount, dbPassword);
login.LoginInit(account, password);
nResult = login.LoginInterface();
}
catch (Exception ex)
{
return ex.Message;
}
return nResult.ToString();
}
[WebMethod]
public string PaysysLogout(string dbName, string dbAccount, string dbPassword, string account)
{
var nResult = 0;
try
{
PlayerLogout logout = new PlayerLogout();
logout.PaysysInit(dbName, dbAccount, dbPassword);
logout.LogoutInit(account);
nResult = logout.LogoutInterface();
}
catch (Exception ex)
{
return ex.Message;
}
return nResult.ToString();
}
之后就可以調(diào)試一下了!
Setp3:部署到IIS(可以查看我之前的一編博客,是一樣的)
http://www.cnblogs.com/Martin_Q/archive/2010/12/06/1897614.html
調(diào)試結(jié)果
遇到問題:
這里遇到一個(gè)很糟糕的問題,使用IIS在調(diào)用到:conn.Open() 的時(shí)候出現(xiàn)一個(gè)錯(cuò)誤:system.data.oracleclient 需要 oracle 客戶端軟件 8.1.7 或更高版本。
這個(gè)問題一定要值得注意,開始我以為是iis沒有權(quán)限訪問oracle目錄,我為什么會(huì)這么認(rèn)為呢?因?yàn)槲覟榱瞬檫@個(gè)問題,我專門寫了一個(gè).exe 去執(zhí)行調(diào)用,exe應(yīng)用程序執(zhí)行成功,iis出錯(cuò)!
原來問題是由于我安裝的oracle客戶端為簡(jiǎn)易版本,很多很多的dll都沒有。可以網(wǎng)上找一下:10201_client_win32.zip 些版本client,當(dāng)然還有其他的權(quán)限問題!這里沒遇到就不談了
Setp4:使用LoadRunner調(diào)用WebServices
1、Loadrunner新建WebService
2、點(diǎn)ManageServices 添加你的WebService地址
3、添加WebService 調(diào)用接口
搭建的地址為:http://10.20.87.62:81/Service.asmx 為什么后面需要手工加一個(gè):?WSDL 呢?(知道的同學(xué)說一下!)
4、添加成功
5、添加對(duì)應(yīng)的存儲(chǔ)過程
6、添加成功后Action代碼
Action()
{
lr_start_transaction("Login");
web_service_call( "StepName=PaysysLogin_101",
"SOAPMethod=Service|ServiceSoap|PaysysLogin",
"ResponseParam=response",
"Service=Service",
"ExpectedResponse=SoapResult",
"Snapshot=t1386150115.inf",
BEGIN_ARGUMENTS, // 參數(shù)傳入
"dbName=orcl_35",
"dbAccount=root",
"dbPassword=123456",
"account={Account}",
"password=a",
END_ARGUMENTS,
BEGIN_RESULT, // 獲取返回值
"PaysysLoginResult=LoginResult",
END_RESULT,
LAST);
lr_message("All:%s\r\nLoginResult:%s\r\n",lr_eval_string("{response}"),lr_eval_string("{LoginResult}"));
if(atoi(lr_eval_string("{LoginResult}")) == 1)
{
lr_end_sub_transaction("Login",LR_PASS);
}
else
{
lr_end_sub_transaction("Login",LR_FAIL);
lr_error_message("Login Error:%s ---- %s",lr_eval_string("{LoginResult}"),lr_eval_string("{Account}"));
}
return 0;
}
輸出結(jié)果:
All:<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><PaysysLoginResponse xmlns="http://tempuri.org/"><PaysysLoginResult>1</PaysysLoginResult></PaysysLoginResponse></soap:Body></soap:Envelope>
LoginResult:1
python寫的數(shù)據(jù)采集,對(duì)一般有規(guī)律的頁面用 urllib2 + BeautifulSoup + 正則就可以搞定。 但是有些頁面的內(nèi)容是通過js生成,或者通過js跳轉(zhuǎn)的,甚至js中還加入幾道混淆機(jī)制;對(duì)這種涉及頁面腳本解析的內(nèi)容,前面的方式便很無力。
這時(shí)我們需要能解析、運(yùn)行js的引擎——瀏覽器,而python selenium能提供程序與瀏覽器的交互接口,再加上phantomjs這個(gè)可以后臺(tái)運(yùn)行的瀏覽器,即使用 selenium + phantomjs 便可以解決以上的問題。
selenium可以操作頁面的元素,并且提供執(zhí)行js腳本的接口。但其調(diào)用js腳本后并不能直接返回執(zhí)行的結(jié)果,這樣再采集內(nèi)容的過程中就會(huì)受到一些限制。 比如我們想使用頁面中的函數(shù)進(jìn)行數(shù)據(jù)轉(zhuǎn)換,或者獲取iframe里的內(nèi)容,這些js產(chǎn)生數(shù)據(jù)要傳回比較麻煩。
所以我便寫一個(gè)簡(jiǎn)化js數(shù)據(jù)回傳的擴(kuò)展 exescript.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# created by heqingpan
_init_js="""
(function (){
if (window.__e)
{ return;
}
var e=document.createElement('div');
e.setAttribute("id","__s_msg");
e.style.display="none";
document.body.appendChild(e);
window.__e=e;
})();
window.__s_set_msg=function(a){
window.__e.setAttribute("msg",a.toString()||"");
}
"""
_loadJsFmt="""
var script = document.createElement('script');
script.src = "{0}";
document.body.appendChild(script);
"""
_jquery_cdn="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"
_warpjsfmt="__s_set_msg({0})"
class ExeJs(object):
def __init__(self,driver,trytimes=10):
from time import sleep
self.driver=driver
driver.execute_script(_init_js)
while trytimes >0:
try:
self.msgNode=driver.find_element_by_id('__s_msg')
break
except Exception:
sleep(1)
trytimes -= 1
if self.msgNode is None:
raise Exception()
def exeWrap(self,jsstr):
""" jsstr 執(zhí)行后有返回值,返回值通過self.getMsg()獲取 """
self.driver.execute_script(_warpjsfmt.format(jsstr))
def loadJs(self,path):
self.execute(_loadJsFmt.format(path))
def loadJquery(self,path=_jquery_cdn):
self.loadJs(path)
def execute(self,jsstr):
self.driver.execute_script(jsstr)
def getMsg(self):
return self.msgNode.get_attribute('msg')
打開ipython上一個(gè)例子,獲取博客園首頁文章title列表
from selenium import webdriver
import exescript
d=webdriver.PhantomJS("phantomjs")
d.get("http://www.cnblogs.com/")
exejs=exescript.ExeJs(d)
exejs.exeWrap('$(".post_item").length')
print exejs.getMsg()
#out:
"""
20
"""
jsstr="""(function(){
var r=[];
$(".post_item").each(function(){
var $this=$(this);
var $h3=$this.find("h3");
r.push($h3.text());
});
return r.join(',');})()"""
exejs.exeWrap(jsstr)
l=exejs.getMsg()
for title in l.split(','):
print title
#out:
"""
mac TeamTalk開發(fā)點(diǎn)點(diǎn)滴滴之一——DDLogic框架分解上
The directfb backend was supported together with linux-fb backend in GTK+2.10
Science上發(fā)表的超贊聚類算法
功能齊全、效率一流的免費(fèi)開源數(shù)據(jù)庫導(dǎo)入導(dǎo)出工具(c#開發(fā),支持SQL server、SQLite、ACCESS三種數(shù)據(jù) 庫),每月借此處理數(shù)據(jù)5G以上
企業(yè)級(jí)應(yīng)用框架(三)三層架構(gòu)之?dāng)?shù)據(jù)訪問層的改進(jìn)以及測(cè)試DOM的發(fā)布
Unity3D 第一季 00 深入理解U3D開發(fā)平臺(tái)
Welcome to Swift (蘋果官方Swift文檔初譯與注解二十一)---140~147頁(第三章--集合類型)
appium簡(jiǎn)明教程(11)——使用resource id定位
SQL語句匯總(終篇)—— 表聯(lián)接與聯(lián)接查詢
fopen警告處理方式
AndroidWear開發(fā)之HelloWorld篇
AMD and CMD are dead之KMD.js版本0.0.2發(fā)布
SQL語句匯總(三)——聚合函數(shù)、分組、子查詢及組合查詢
DevExpress GridControl功能總結(jié)
ASP.NET之Jquery入門級(jí)別
2014年前端面試經(jīng)歷
grunt源碼解析:整體運(yùn)行機(jī)制&grunt-cli源碼解析
跟用戶溝通,問題盡量分析清楚,以及解決問題
ASP.NET之Ajax系列(一)
算法復(fù)雜度分析
"""
具體需求: 有一個(gè)登陸頁面, (假如上面有2個(gè)textbox, 一個(gè)提交按鈕。 請(qǐng)針對(duì)這個(gè)頁面設(shè)計(jì)30個(gè)以上的
test case.)
此題的考察目的:
面試 者是否熟悉各種
測(cè)試 方法,是否有豐富的
Web測(cè)試 經(jīng)驗(yàn), 是否了解Web開發(fā),以及設(shè)計(jì)Test case的能力
這個(gè)題目還是相當(dāng)有難度的, 一般的人很難把這個(gè)題目回答好。
首先,你要了解用戶的需求,比如這個(gè)登錄界面應(yīng)該是彈出窗口式的,還是直接在網(wǎng)頁里面。對(duì)用戶名的長(zhǎng)度,和密碼的強(qiáng)度(就是是不是必須多少位,大小寫,特殊字符混搭)等。還有比如用戶對(duì)界面的美觀是不是有特殊的要求?(即是否要進(jìn)行UI測(cè)試)。剩下的就是設(shè)計(jì)用例了 ,等價(jià)類,邊界值等等。
請(qǐng)你記住一點(diǎn),任何測(cè)試,不管測(cè)什么都是從了解需求開始的。
0. 什么都不輸入,點(diǎn)擊提交按鈕,看提示信息。
1.輸入正確的用戶名和密碼,點(diǎn)擊提交按鈕,驗(yàn)證是否能正確登錄。
2.輸入錯(cuò)誤的用戶名或者密碼, 驗(yàn)證登錄會(huì)失敗,并且提示相應(yīng)的錯(cuò)誤信息。
3.登錄成功后能否能否跳轉(zhuǎn)到正確的頁面
4.用戶名和密碼,如果太短或者太長(zhǎng),應(yīng)該怎么處理
5.用戶名和密碼,中有特殊字符(比如空格),和其他非英文的情況
6.記住用戶名的功能
7.登陸失敗后,不能記錄密碼的功能
8.用戶名和密碼前后有空格的處理
9.密碼是否加密顯示(星號(hào)圓點(diǎn)等)
10.牽扯到驗(yàn)證碼的,還要考慮文字是否扭曲過度導(dǎo)致辨認(rèn)難度大,考慮顏色(色盲使用者),刷新或換一個(gè)按鈕是否好用
11.登錄頁面中的注冊(cè)、忘記密碼,登出用另一帳號(hào)登陸等鏈接是否正確
12.輸入密碼的時(shí)候,大寫鍵盤開啟的時(shí)候要有提示信息。
1.布局是否合理,2個(gè)testbox 和一個(gè)按鈕是否對(duì)齊
2.testbox和按鈕的長(zhǎng)度,高度是否復(fù)合要求
3. 界面的設(shè)計(jì)風(fēng)格是否與UI的設(shè)計(jì)風(fēng)格統(tǒng)一
4. 界面中的文字簡(jiǎn)潔易懂,沒有錯(cuò)別字。
1.打開登錄頁面,需要幾秒
2.輸入正確的用戶名和密碼后,登錄成功跳轉(zhuǎn)到新頁面,不超過5秒
安全性測(cè)試(Security test)
1.登錄成功后生成的Cookie,是否是httponly (否則容易被腳本盜取)
2.用戶名和密碼是否通過加密的方式,發(fā)送給Web服務(wù)器
3.用戶名和密碼的驗(yàn)證,應(yīng)該是用服務(wù)器端驗(yàn)證, 而不能單單是在客戶端用javascript驗(yàn)證
4.用戶名和密碼的輸入框,應(yīng)該屏蔽
SQL 注入攻擊
5.用戶名和密碼的的輸入框,應(yīng)該禁止輸入腳本 (防止XSS攻擊)
6.錯(cuò)誤登陸的次數(shù)限制(防止暴力破解)
7. 考慮是否支持多用戶在同一機(jī)器上登錄;
8. 考慮一用戶在多臺(tái)機(jī)器上登錄
可用性測(cè)試(Usability Test)
1. 是否可以全用鍵盤操作,是否有快捷鍵
2. 輸入用戶名,密碼后按回車,是否可以登陸
3. 輸入框能否可以以Tab鍵切換
兼容性測(cè)試(Compatibility Test)
1.主流的瀏覽器下能否顯示正常已經(jīng)功能正常(IE,6,7,8,9, Firefox, Chrome, Safari,等)
3.移動(dòng)設(shè)備上是否正常工作,比如Iphone, Andriod
4.不同的分辨率
本地化測(cè)試 (Localization test)
1. 不同語言環(huán)境下,頁面的顯示是否正確。
軟件輔助性測(cè)試 (Accessibility test)
軟件輔助功能測(cè)試是指測(cè)試軟件是否向殘疾用戶提供足夠的輔助功能
1. 高對(duì)比度下能否顯示正常 (視力不好的人使用)
主站蜘蛛池模板:
仙游县 |
公主岭市 |
钟祥市 |
三明市 |
廊坊市 |
绍兴市 |
东乡族自治县 |
朝阳市 |
石嘴山市 |
札达县 |
彭阳县 |
项城市 |
维西 |
芜湖县 |
庐江县 |
潼关县 |
台湾省 |
长白 |
丹东市 |
扶余县 |
屏边 |
松潘县 |
洛阳市 |
慈溪市 |
静乐县 |
车险 |
永平县 |
昌邑市 |
玛纳斯县 |
定日县 |
柳河县 |
霍城县 |
高邮市 |
阿拉善右旗 |
潜江市 |
南华县 |
阿克陶县 |
乐平市 |
石渠县 |
西乡县 |
喀什市 |