<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經轉移至github,大家請訪問 http://qaseven.github.io/

    IOS操作系統的層次結構

      1、Core OS 核心層:包含Accelerate Framework、External Accessory Framework、Security Framework、System等幾個框架,基本都是基于c語言的接口
      2、Core Services核心服務層:包含Address Book Framework、CFNetwork Framework、Core Data Framework、Core Foundation Framework、Core Location Framework、Core Media Framework、Core Telephony Framework、Event Kit Framework、Foundation Framework、Mobile Core Services Framework、Quick Look Framework、Store Kit Framework、System Configuration Framework、Block Objects、Grand Central Dispatch  、In App Purchase、Location Services、SQLite、XML Support等一些框架,也基本都是基于c語言的接口。
      3、Mediah媒體層:包含Core Graphics、Core Animation、OpenGL ES、Core Text、Image I/O、Assets Library Framework、Media Player Framework、AV Foundation、OpenAL、Core Audio Frameworks、Core Media等等
      4、 Cocoa Touch 觸摸層:包括Address Book UI Framework、Event Kit UI Framework、Game Kit Framework、iAd Framework、Map Kit Framework、Message UI Framework、UIKit Framework等等,這一層基本都是基于 Objective-c的接口

    posted @ 2014-06-10 09:50 順其自然EVO 閱讀(1414) | 評論 (0)編輯 收藏

    ORACLE數據庫的優化

    CPU參數的調整
      CPU是服務器的一項重要資,服務器良好的工作狀態是在工作高峰時CPU的使用在90%以上。如果空閑時間CPU使用率就在90%以上,說明服務器缺乏CPU資源,如果工作高峰時CPU使用率仍然恨低,說明服務器CPU資源還比較富余。
      使用操作相同命令可以看到CPU的使用情況,以般UNIX操作系統的服務器,可以使用sar–u命令查看CPU的使用率,NT操作系統的服務器,可以使用NT的性能管理器來查看CPU的使用率。
      數據庫管理員可以通過查看v$sysstat(select*fromv$sysstat wherenamelike'CPU%')數據字典中“CPUused by this session”統計項得知ORACLE數據庫使用的CPU時間,查看“OS Userlevel CPU time“統計項得知操作系統用戶態的CPU時間,查看“OS Systemcall CPU time“統計項得知操作系統系統態下的CPU時間,操作系統總的CPU時間就是用戶態和系統態時間之和,如果ORACLE數據庫使用的CPU時間占操作系統總的CPU時間90%以上,說明服務器CPU基本上被ORACLE數據庫使用著,這是合理,反之,說明服務器CPU被其它程序占用過多,ORACLE數據庫無法得到更多的CPU時間。
      數據庫管理員還可以通過查看v$sesstat數據字典來獲得當前連接ORACLE數據庫各個會話占用的CPU時間,從而得知什么會話耗用服務器CPU比較多。(select*fromv$sysstat orderbyvaluedesc)
      出現CPU資源不足的情況是很多的:SQL語句的重解析、低效率的SQL語句、鎖沖突都會引起CPU資源不足。
      1、數據庫管理員可以執行下述語句來查看SQL語句的解析情況:
      SELECT * FROM V$SYSSTAT
      WHERE NAME IN
      ('parse time cpu', 'parse time elapsed', 'parse count (hard)');
      這里parse time cpu是系統服務時間,parse timeelapsed是響應時間,用戶等待時間
      waite time = parse time elapsed – parse time cpu
      由此可以得到用戶SQL語句平均解析等待時間=waite time / parse count,這個平均等待時間應該接近于0,如果平均解析等待時間過長,數據庫管理員可以通過下述語句
      SELECTSQL_TEXT, PARSE_CALLS, EXECUTIONS FROM V$SQLAREA
      ORDER BY PARSE_CALLS;
      來發現是什么SQL語句解析效率比較低。程序員可以優化這些語句,或者增加ORACLE參數SESSION_CACHED_CURSORS的值。
      2、數據庫管理員還可以通過下述語句:
      SELECT BUFFER_GETS, EXECUTIONS, SQL_TEXT FROMV$SQLAREA;
      查看低效率的SQL語句,優化這些語句也有助于提高CPU的利用率。
      3、數據庫管理員可以通過v$system_event(select*fromv$system_event where event like'_atch%';)數據字典中的”latchfree“統計項查看ORACLE數據庫的沖突情況,如果沒有沖突的話,latch free查詢出來沒有結果。如果沖突太大的話,數據庫管理員可以降低spin_count參數值,來消除高的CPU使用率。

    內存參數的調整
      內存參數的調整主要是指ORACLE數據庫的系統全局區(SGA)的調整。SGA主要由三部分構成:共享池、數據緩沖區、日志緩沖區。
      1、   共享池由兩部分構成:共享SQL區和數據字典緩沖區,共享SQL區是存放用戶SQL命令的區域,數據字典緩沖區存放數據庫運行的動態信息。數據庫管理員通過執行下述語句:
      select (sum(pins -reloads)) / sum(pins) "Lib Cache" from v$librarycache;
      來查看共享SQL區的使用率。這個使用率應在90%以上,否則需要增加共享池的大小。數據庫管理員還可以執行下述語句:
      select (sum(gets - getmisses - usage - fixed))/ sum(gets) "Row Cache" from v$rowcache;
      查看數據字典緩沖區的使用率,這個使用率也應該在90%以上,否則需要增加共享池的大小。
      2、   數據緩沖區.數據庫管理員可以通過下述語句:
      SELECT name, value  FROM v$sysstat  WHERE name IN ('db block gets', 'consistentgets','physical reads');
      來查看數據庫數據緩沖區的使用情況。查詢出來的結果可以計算出來數據緩沖區的使用命中率=1 - ( physical reads / (db block gets + consistent gets))。
      這個命中率應該在90%以上,否則需要增加數據緩沖區的大小。
      3、   日志緩沖區.數據庫管理員可以通過執行下述語句:
      select name,value from v$sysstat where name in('redo entries','redo log space requests');查看日志緩沖區的使用情況。查詢出的結果可以計算出日志緩沖區的申請失敗率:
      申請失敗率=requests/entries,申請失敗率應該接近于0,否則說明日志緩沖區開設太小,需要增加ORACLE數據庫的日志緩沖區。

    posted @ 2014-06-10 09:49 順其自然EVO 閱讀(179) | 評論 (0)編輯 收藏

    單元測試—使用模擬對象做交互測試

      最近在看.net單元測試藝術,我也喜歡單元測試,這里寫一下如何在測試中使用模擬對象。
      開發的過程中,我們都會遇到對象間的依賴,比如依賴數據庫或文件,這時,我們需要使用模擬對象,來進行測試,我們可以手寫模擬對象,當然也可以使用模擬框架。
      假如有這樣的一個需求,當用戶登陸時,我需要對用戶名和密碼進行驗證,然后再將用戶名寫入日志中。
    public class MyLogin
    {
    public ILog Log { get; set; }
    public bool Valid(string userName, string passWord)
    {
    var isValid = userName == "admin" && passWord == "123456";
    Log.Write(userName);
    return isValid;
    }
    }
    public interface ILog
    {
    void Write(string message);
    }
      上面的代碼在驗證完登陸信息后,需要向日志中寫入用戶名,由于寫入日志可能依賴于文件或數據庫,我們可能很難進行測試,所以,這里使用模擬對象進行測試。手寫模擬對象,代碼如下:
    public class MyLoginTest
    {
    [Test]
    public void Vaild_Test()
    {
    MyLogin login = new MyLogin();
    var log = new TestLog();
    login.Log = log;
    var userNmae = "admin";
    var passWord = "123456";
    var isLogin = login.Valid(userNmae, passWord);
    Assert.AreEqual(isLogin, true);
    Assert.AreEqual(log.Message, userNmae);
    }
    }
    public class TestLog : ILog
    {
    public string Message;
    public void Write(string message)
    {
    this.Message = message;
    }
    }
      這里我們定義了一個對象TestLog對象,該對象就是一個模擬對像,繼承了ILog接口。該測試中,一共進行了兩項測試。一項是:驗證用戶名和密碼是否輸入正確。另一項是:驗證用戶寫入日志的信息是否正確(比如應該寫入用戶名,結果把密碼寫入了日志,測試會無法通過)。
      這里我們區分一下模擬對象與樁對象。上一節中,我們講過樁對象的定義,那么模擬對象與樁對象是什么關系呢?
      模擬對象與樁對象在寫法上區別很小,關鍵在于模擬對象需要進行斷言,也就是說模擬對象可以導致測試失敗。樁對象只是為了方便測試所定義的一個對象,不需要進行斷言,所以,樁對象永遠不會導致測試失敗。
      上面的測試中,如果我們去掉最后一行代碼,即我們不進行寫入日志的斷言,則該對象就是一個樁對象。
      Assert.AreEqual(log.Message, userNmae);
      上面的模擬對象是我們自己寫的,自己寫模擬對象比較費時,我們可以使用模擬框架進行編寫。這里我使用了Rhino Mocks框架。如果要執行下面的代碼,需要下載Rhino.Mocks.dll文件,然后直接引用即可。
      測試框架這里我選用了NUnit框架。測試代碼如下:
    [TestFixture]
    public class MyLoginTest
    {
    [Test]
    public void Mock_Vaild_Test()
    {
    MockRepository mock = new MockRepository();
    var log = mock.DynamicMock<ILog>();
    var userName = "admin";
    var passWord = "123456";
    using (mock.Record())
    {
    log.Write(userName);
    }
    MyLogin login = new MyLogin();
    login.Log = log;
    var isLogin = login.Valid(userName, passWord);
    Assert.AreEqual(isLogin, true);
    mock.VerifyAll();
    }
      這里我沒有編寫一個類去繼承ILog接口,而是通過模擬框架,動態生成了一個ILog對象。代碼是這句:
      MockRepository mock = new MockRepository();
      var log = mock.DynamicMock<ILog>();
      這里便生成了Log對象。通過錄制-回放的模式進行模擬對象測試,首先需要定義我們的期望行為,最后驗證實際行為與期望行為是否一致。這里,需要錄制我們期望行為,代碼如下:
    using (mock.Record())
    {
    log.Write(userName);
    }
      這里我們期望向日志中寫入用戶名。再通過回放來進行驗證,代碼如下:
      mock.VerifyAll();
      該方法會驗證,期望向日志中寫入的信息與實際向日志中寫入的信息是否一致,如果不一致,測試失敗。
      這里我們便完成了使用模擬框架進行單元測試。如果我們不需要測試日志寫入方法,則把模擬對象換成樁對象就可以了,生成樁對象的方法如下:
      MockRepository mock = new MockRepository();
      var log = mock.Stub<ILog>();
      把回放的方法(mock.VerifyAll())去掉,就完成了模擬對象向樁對象的轉變。注意,這里錄制的代碼還是需要的。
      總結:編寫模擬對象和樁對象是非常有意義的,使用框架可以幫助我們簡化單元測試。一般情況下,一個測試中,可以有多個樁對象,但最好只有一個模擬對象。模擬對象太多,證明一個測試方法做了太多項測試,不利于維護測試代碼,一旦代碼變改,很容易使單元測試失敗。
      下一節,寫一下測試框架的一些常用功能,如:如何模擬異常、如何模擬返回值等。。。

    posted @ 2014-06-10 09:48 順其自然EVO 閱讀(275) | 評論 (0)編輯 收藏

    支付寶分布式事務測試方案

      傳統的基于數據庫本地事務的解決方案只能保障單個服務的一次處理具備原子性、隔離性、一致性與持久性,但無法保障多個分布服務間處理的一致性。因此,我們必須建立一套分布式服務處理之間的協調機制,保障分布式服務處理的原子性、隔離性、一致性與持久性。
      支付寶為什么需要分布式事務
      基于SOA架構,整個支付寶系統會拆分成一系列獨立開發、自包含、自主運行的業務服務,并將這些服務通過各種機制靈活地組裝成最終用戶所需要的產品與解決方案。
      在多個服務協同完成一次業務時,由于業務約束(如紅包不符合使用條件、賬戶余額不足等)、系統故障(如網絡或系統超時或中斷、數據庫約束不滿足等),都可能造成服務處理過程在任何一步無法繼續,使數據處于不一致的狀態,產生嚴重的業務后果,所以我們需要一個分布式事務的解決方案,用來協調多個服務的業務一致性。
      支付寶的分布式事務框架
      支付寶開發的分布式事務是基于兩階段提交的理論(Two Phase Commit),首先給出兩階段提交的邏輯圖:
      為了能夠有效的讓框架進行分布式事務的提交、回滾等動作,框架需要在整個兩階段執行過程中記錄下足夠的信息,設計了兩張表來記錄相關信息:
      分布式業務控制活動主表:記錄了全局事務的活動狀態;
      原子業務活動表:記錄了原子業務活動的狀態;
      我們用一個例子來說明:
      看一個典型的分布式事務場景。
      業務場景描述: 用戶購買商品,使用支付寶余額支付;
      測試方案
      分析步驟
      角色定位
      各分支的業務活動記錄狀態
      梳理業務各個場景
      驗證梳理場景
      恢復&回查機制
      角色定位
      首先測試人員需要分析所測試的系統處于分布式事務中的哪一個環節中,是處于事務的發起者,還是事務的參與者,不同的角色的定位對于測試分析角度不同,主要有以下的區別:
      發起者:
      分為同庫/異庫模式,主要區分是控制全局事務狀態的主事務記錄是否持久化在自己系統的db中;
      參與者:
      分為本地/遠程模式,主要區分是是否可以創建嵌套的分布式事務;
      各分支的業務活動記錄狀態
      主事務記錄:
      根據業務場景的不同,主事務記錄狀態也會相應改變,主要的狀態機變化如圖所示,測試人員需要模擬業務場景來驗證狀態機的遷轉是否正確;
      同庫:初始狀態:I;提交成功:C;提交失敗:I
      異庫:初始狀態:U;提交成功:U;提交失敗:U

     梳理&驗證業務場景
      分析維度
      一階段:預處理:成功/失敗;
      二階段:提交/回滾;
      預期結果
      各個狀態場景
      恢復&回查
      恢復:應用使用分布式事務,出現處理失敗的業務活動,為了確保產生的影響不破壞業務一致性,我們必須對這些記錄進行恢復處理
      回查:對于異庫模式,事務狀態為U,若提交或回滾失敗,分布式事務總控系統無法感知這筆分布式事務是否執行成功,需要業務系統提供相應的回查接口;
      恢復及回查接口需要特別關注,對于分布式事務的正常二階段提交或回滾,業務場景覆蓋時多半都能check到,但是對于恢復及回查邏輯,很多時候都會遺漏,所以測試人員需要對這塊特別做一個分析

    posted @ 2014-06-10 09:47 順其自然EVO 閱讀(359) | 評論 (0)編輯 收藏

    并發性能測試程序編寫

     一般要測試軟件或者庫的性能,需要在多線程條件下進行。本文提供一種編寫多線程性能測試的模板,方便大家參考和使用。
      本文以AES加密和解密為例,并指出Cipher的獲取在程序中的不同位置會對程序性能造成的影響。
      程序代碼如下:
    package com.lazycat.secure.aes;
    import java.nio.charset.Charset;
    import java.security.NoSuchAlgorithmException;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import javax.crypto.Cipher;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.SecretKeySpec;
    public class AESCoder {
    public static int count = 1000000;
    public static CountDownLatch latch =new CountDownLatch(count);
    public static void main(String[] args)throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(200);
    final byte[] payload = "{\"msg\":{\"content\":{\"text\":\"JJH\",\"tplId\":0},\"from\":{\"name\":\"10000213\",\"id\":1,\"type\":0},\"to\":{\"name\":\"10095812\",\"id\":10000213,\"type\":0},\"time\":0,\"txid\":0,\"subtype\":1},\"type\":\"chat\"}".getBytes(Charset.forName("utf-8"));
    final String secureKey ="BBmFdTFVgAjgHNwRkWWRcOFFiBzAANFU9DmMAP1JpBmc.";
    long start = System.currentTimeMillis();
    for(int i = 0 ; i <count ; i++){
    pool.execute(new Runnable() {
    public void run() {
    AESCoder coder = new AESCoder();
    byte[] enret =null;
    try {
    enret = coder.encrypt(payload,secureKey);
    byte[] deret = coder.decrypt(enret, secureKey);
    System.out.println(new String(deret,"utf-8"));
    } catch (Exception e) {
    e.printStackTrace();
    }
    latch.countDown();
    }
    });
    }
    latch.await();
    System.out.println(System.currentTimeMillis() - start);
    pool.shutdown();
    }
    private byte[] encrypt(byte[] payload,String securekey)throws Exception{
    byte[] enCodeFormat = securekey.substring(0, 16).getBytes();
    SecretKeySpec key = newSecretKeySpec(enCodeFormat,"AES");
    Cipher cipher = CliperInstance.getInstance();//創建密碼器
    //Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);//初始化
    byte[] result = cipher.doFinal(payload);
    return result;
    }
    public byte[] decrypt(byte[] buffer,StringsecureKey)throws Exception{
    byte[] enCodeFormat = secureKey.substring(0,16).getBytes();
    SecretKeySpec key = newSecretKeySpec(enCodeFormat,"AES");
    //Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//創建密碼器
    Cipher cipher = CliperInstance.getInstance();
    cipher.init(Cipher.DECRYPT_MODE, key);//初始化
    byte[] result = cipher.doFinal(buffer);
    return result;
    }
    }
    class CliperInstance {
    private static ThreadLocal<Cipher> cipherTL =new ThreadLocal<Cipher>(){
    @Override
    protected Cipher initialValue() {
    try {
    return Cipher.getInstance("AES/ECB/PKCS5Padding");
    }catch(Exception e){
    return null;
    }
    }
    };
    public static   CiphergetInstance() throws NoSuchAlgorithmException, NoSuchPaddingException{
    returncipherTL.get();
    }
    }
     上述代碼中有兩個方法,分別是encrypt和decryption,分別表示加密和解密。
      為了簡單,可以被多個線程共用,因此將CountDownLatch定義為static。
      在main函數中,創建了固定大小的線程池(200個線程,這個可以根據需要進行調整)和用于加密的payload和秘鑰secureKey。Start用于記錄開始時間,通過最后的System.currentTimeMillis()-start即可獲得程序的運行時間。在for循環中,并發執行了count(10W)次payload的加密和解密,每個線程在執行完一個任務后會調用latch.countDown(),而主程序在循環后使用latch.await(),等待所有線程執行結束后,統計執行時間,輸出消耗時間,最后關閉線程池。
      一般在做對比或者尋找瓶頸時,才會使用性能測試,下面給出一個性能對比的例子。
      在前面的代碼中,無論是encrypt,還是decrypt,都有如下內容:
      Cipher cipher = CliperInstance.getInstance();//創建密碼器
      //Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
      現在我們要對比每次加密和解密都執行Cipher.getInstance方法和對每一個線程自己都維護一個Cipher實例的性能差別。(我們都知道,Ciper.getInstance的調用時很耗時的)。
      使用Ciphercipher = CliperInstance.getInstance(); 時,執行100W次加密和解密,大約使用11.2s,而使用Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 大約需要39.6s,因此在進行加密、解密、簽名等算法時,最好每個線程維護一個加密、解密或者簽名的實例(這些實例是不能再多線程間共享的,如上例所示,調用init和doFinal必須在一個線程內完成,如果全局共享同一個實例,A調用init,B也調用了init,當A調用doFinal時,此時實例內的數據已經不是A的了,會出現異常)。
      順便說一下,如果要求每個線程有自己的實例的情況下(如上面的加密和解密等),那么就可以使用ThreadLocal,在使用ThreadLocal時,重寫內部的initialValue 方法,每次調用ThreadLocal的get方法時,ThreadLocal實例先到自己的Map中尋找有沒有當前線程對應的Instance,如果存在,將Instance返回,如果不存在,調用initialValue去創建一個Instance,并將新Instance放到Map中后,返回。詳情參看JDK文檔。
      需要注意的是,CliperInstance 沒必要非點單寫成一個類,這里是為了讓代碼更容易懂。

    posted @ 2014-06-10 09:46 順其自然EVO 閱讀(479) | 評論 (0)編輯 收藏

    Android自動測試之monkeyrunner工具

    前言:
      最近開始研究Android自動化測試方法,對其中的一些工具、方法和框架做了一些簡單的整理,其中包括android測試框架、CTS、Monkey、Monkeyrunner、benchmark、其它test tool等等。因接觸時間很短,很多地方有不足之處,希望能和大家多多交流。
      一、什么是monkeyrunner
      monkeyrunner工具提供了一個API,使用此API寫出的程序可以在Android代碼之外控制Android設備和模擬器。通過monkeyrunner,您可以寫出一個Python程序去安裝一個Android應用程序或測試包,運行它,向它發送模擬擊鍵,截取它的用戶界面圖片,并將截圖存儲于工作站上。monkeyrunner工具的主要設計目的是用于測試功能/框架水平上的應用程序和設備,或用于運行單元測試套件,但您當然也可以將其用于其它目的。
      二、monkeyrunner工具同Monkey工具的差別
      Monkey:
      Monkey工具直接運行在設備或模擬器的adb shell中,生成用戶或系統的偽隨機事件流。
      monkeyrunner:
      monkeyrunner工具則是在工作站上通過API定義的特定命令和事件控制設備或模擬器。
      三、monkeyrunner的測試類型
      1、多設備控制:monkeyrunner API可以跨多個設備或模擬器實施測試套件。您可以在同一時間接上所有的設備或一次啟動全部模擬器(或統統一起),依據程序依次連接到每一個,然后運行一個或多個測試。您也可以用程序啟動一個配置好的模擬器,運行一個或多個測試,然后關閉模擬器。
      2、 功能測試: monkeyrunner可以為一個應用自動貫徹一次功能測試。您提供按鍵或觸摸事件的輸入數值,然后觀察輸出結果的截屏。
      3、 回歸測試:monkeyrunner可以運行某個應用,并將其結果截屏與既定已知正確的結果截屏相比較,以此測試應用的穩定性。
      4、 可擴展的自動化:由于monkeyrunner是一個API工具包,您可以基于Python模塊和程序開發一整套系統,以此來控制Android設備。除了使用monkeyrunner API之外,您還可以使用標準的Python os和subprocess模塊來調用Android Debug Bridge這樣的Android工具。
      四、運行monkeyrunner
      您可以直接使用一個代碼文件運行monkeyrunner,抑或在交互式對話中輸入monkeyrunner語句。不論使用哪種方式,您都需要調用SDK目錄的tools子目錄下的monkeyrunner命令。如果您提供一個文件名作為運行參數,則monkeyrunner將視文件內容為Python程序,并加以運行;否則,它將提供一個交互對話環境。
      monkeyrunner的命令語法為:
      monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>
      五、實例
      以sample中的ApiDemos為例,先將其生成ApiDemos.apk。
      前提:已有device連接
      1、 將ApiDemos.apk放在$Android_Root\tools下。
      2、 在$Android_Root\tools下新建一個monkeyrunnerprogram.py文件,里面內容為:
    1 # Imports the monkeyrunner modules used by this program
    2
    3  from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
    4
    5  # Connects to the current device, returning a MonkeyDevice object
    6
    7 device = MonkeyRunner.waitForConnection()
    8
    9  # Installs the Android package. Notice that this method returns a boolean, so you can test
    10
    11  # to see if the installation worked.
    12
    13 device.installPackage('./ApiDemos.apk')
    14
    15
    16  # Runs the component
    17
    18 device.startActivity(component='com.example.android.apis/.ApiDemos')
    19
    20
    21  # Presses the Menu button
    22
    23 device.press('KEYCODE_MENU','DOWN_AND_UP')
    24
    25
    26  # Takes a screenshot
    27
    28 result = device.takeSnapshot()
    29
    30
    31  # Writes the screenshot to a file
    32
    33 result.writeToFile('./shot1.png','png')
     注意:SDK上的例子有些錯誤,不可直接復制,否則執行命令時會發生錯誤。具體可與我的上面這段代碼對照。
      3、 打開命令行轉到Android_Root\tools目錄下運行一下命令:
    monkeyrunner monkeyrunnerprogram.py
    110307 15:33:19.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:20.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:21.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice] Error starting command: monkey --port 12345
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]com.android.ddmlib.ShellCommandUnresponsiveException
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:408)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.ddmlib.Device.executeShellCommand(Device.java:276)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.monkeyrunner.adb.AdbMonkeyDevice$1.run(AdbMonkeyDevice.java:89)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.Executors$RunnableAdapter.call(UnknownSource)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.FutureTask.run(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.ThreadPoolExecutor$Worker.run(UnknownSource)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.lang.Thread.run(UnknownSource)
    110307 15:33:57.437:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: press KEYCODE_MENU.
    110307 15:33:59.171:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: quit.
      注:里面exception的提示我們可以忽略,因為我們可以看見 Monkey Command: press KEYCODE_MENU已經執行成功。
      4、 可以Android_Root\tools下查看生成的shot1.png的截圖。
      六、實例擴展
      因為ApiDemos首頁上按下MENU鍵沒有菜單出現,為了更加形象化,在實例五的基礎上繼續試驗:
      1、 在$Android_Root\tools下新建一個monkeyrunnerprogram1.py文件,里面內容為:
    1 # Imports the monkeyrunner modules used by this program
    2
    3  from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
    4
    5 # Connects to the current device, returning a MonkeyDevice object
    6
    7 device = MonkeyRunner.waitForConnection()
    8
    9 # Takes a screenshot
    10
    11 result = device.takeSnapshot()
    12
    13 # Writes the screenshot to a file
    14
    15 result.writeToFile('./shotbegin.png','png')
    16
    17 # Presses the Down button
    18
    19 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    20
    21 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    22
    23 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    24
    25 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    26
    27 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    28
    29 # Takes a screenshot
    30
    31 result = device.takeSnapshot()
    32
    33 # Writes the screenshot to a file
    34
    35 result.writeToFile('./shotend.png','png')
      2、  將畫面定位在Apidemos的首頁,并將光標定位在第一項上。
      3、  在$Android_Root\tools目錄下運行一下命令:
      monkeyrunner monkeyrunnerprogram1.py
      4、在運行過程中我們可以看見光標不斷向下移動,并且可以在當前目錄下我們自定義的截圖:
      運行前:
      運行后(做了五次下移操作):

    posted @ 2014-06-10 09:45 順其自然EVO 閱讀(182) | 評論 (0)編輯 收藏

    Java中RMI遠程調用

     Java遠程方法調用,即Java RMI(Java Remote Method Invocation)是Java編程語言里,一種用于實現遠程過程調用的應用程序編程接口。它使客戶機上運行的程序可以調用遠程服務器上的對象。遠程方法調用特性使Java編程人員能夠在網絡環境中分布操作。RMI全部的宗旨就是盡可能簡化遠程接口對象的使用。
      Java RMI極大地依賴于接口。在需要創建一個遠程對象的時候,程序員通過傳遞一個接口來隱藏底層的實現細節。客戶端得到的遠程對象句柄正好與本地的根代碼連接,由后者負責透過網絡通信。這樣一來,程序員只需關心如何通過自己的接口句柄發送消息。
      服務端新建接口:
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    public interface RmiTestInterface extends Remote{
    public String getTest() throws RemoteException;
    }
      接口的實現:
    import java.rmi.RemoteException;
    public class RmiTestImpl implements RmiTestInterface {
    public RmiTestImpl() throws RemoteException {
    //super();
    // TODO Auto-generated constructor stub
    //UnicastRemoteObject.exportObject(this);
    }
    /**
    *
    */
    public String getTest() throws RemoteException {
    // TODO Auto-generated method stub
    return "Hello,Test";
    }
    }
      定義一個main方法,注冊你已經實現的RMI接口,包括開放端口等:
    public static void main(String []args) throws AlreadyBoundException, RemoteException{
    RmiTestImpl t=new RmiTestImpl();
    RmiTestInterface tt=(RmiTestInterface)UnicastRemoteObject.exportObject(t,0);
    // Bind the remote object's stub in the registry
    Registry registry = LocateRegistry.createRegistry(2001);
    registry.rebind("test", tt);
    System.out.println("server is start");
    }
     Server端的代碼已經全部寫完,但是還要把接口類(RmiTestInterface)打包成jar,導入進client端的項目中。
      運行服務端后控制臺輸出:
      server is start
      導入服務端的接口jar以后,可以開始編寫一個client端的主程序:
    public static void main(String []args){
    try {
    Registry registry = LocateRegistry.getRegistry("localhost",2001);
    RmiTestInterface t= (RmiTestInterface) registry.lookup("test");
    System.out.println("client:"+t.getTest());
    } catch (RemoteException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (NotBoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
      運行客戶端main方法后,控制臺輸出:
      Hello,Test
    English »
     
    English »
     

    posted @ 2014-06-09 10:36 順其自然EVO 閱讀(153) | 評論 (0)編輯 收藏

    MySQL數據庫如何做好優化

     碰到過好幾次這樣的題目,可每次都不能答的完全正確,現在大概列出如下:(望各位補充)
      1.數據庫的設計
      (盡量把數據庫設計的更小的占磁盤空間。
      (1).盡可能使用更小的整數類型。(mediumint就比int更合適)。
      (2).盡可能的定義字段為not null,除非這個字段需要null。
      (3).如果沒有用到變長字段的話比如varchar,那就采用固定大小的紀錄格式比如char。
      (4).表的主索引應該盡可能的短,這樣的話每條紀錄都有名字標志且更高效。
      (5).只創建確實需要的索引。索引有利于檢索記錄,但是不利于快速保存記錄。如果總是要在表的組合字段上做搜索,那么就在這些字段上創建索引。索引的第一部分必須是最常使用的字段。如果總是需要用到很多字段,首先就應該多復制這些字段,使索引更好的壓縮。
      (6).所有數據都得在保存到數據庫前進行處理。
      (7).所有字段都得有默認值。
      (8).在某些情況下,把一個頻繁掃描的表分成兩個速度會快好多。在對動態格式表掃描以取得相關記錄時,它可能使用更小的靜態格式表的情況下更是如此。
      2.系統的用途
      (1).盡量使用長連接。
      (2).explain 復雜的SQL語句。
      (3).如果兩個關聯表要做比較話,做比較的字段必須類型和長度都一致。
      (4).LIMIT語句盡量要跟 order by 或者 distinct。這樣可以避免做一次full table scan。
      (5).如果想要清空表的所有紀錄,建議用 truncate table tablename 而不是 delete from tablename。
      (6).能使用 STORE PROCEDURE 或者 USER FUNCTION的時候。
      (7).在一條insert語句中采用多重紀錄插入格式,而且使用 load data infile 來導入大量數據,這比單純的indert快好多。
      (8).經常 OPTIMIZE TABLE 來整理碎片。
      (9).還有就是 date 類型的數據如果頻繁要做比較的話盡量保存在 unsigned int 類型比較快。
      3.系統的瓶頸
      (1).磁盤搜索
      并行搜索,把數據分開存放到多個磁盤中,這樣能加快搜索時間.
      (2).磁盤讀寫(IO)
      可以從多個媒介中并行的讀取數據。
      (3).CPU周期
      數據存放在主內存中,這樣就得增加CPU的個數來處理這些數據。
      (4).內存帶寬
      當CPU要將更多的數據存放到CPU的緩存中來的話,內存的帶寬就成了瓶頸.
    English »
     

    posted @ 2014-06-09 10:34 順其自然EVO 閱讀(175) | 評論 (0)編輯 收藏

    Android自動測試之monkeyrunner工具

     前言:
      最近開始研究Android自動化測試方法,對其中的一些工具、方法和框架做了一些簡單的整理,其中包括android測試框架、CTS、Monkey、Monkeyrunner、benchmark、其它test tool等等。因接觸時間很短,很多地方有不足之處,希望能和大家多多交流。
      一、什么是monkeyrunner
      monkeyrunner工具提供了一個API,使用此API寫出的程序可以在Android代碼之外控制Android設備和模擬器。通過monkeyrunner,您可以寫出一個Python程序去安裝一個Android應用程序或測試包,運行它,向它發送模擬擊鍵,截取它的用戶界面圖片,并將截圖存儲于工作站上。monkeyrunner工具的主要設計目的是用于測試功能/框架水平上的應用程序和設備,或用于運行單元測試套件,但您當然也可以將其用于其它目的。
      二、monkeyrunner工具同Monkey工具的差別
      Monkey:
      Monkey工具直接運行在設備或模擬器的adb shell中,生成用戶或系統的偽隨機事件流。
      monkeyrunner:
      monkeyrunner工具則是在工作站上通過API定義的特定命令和事件控制設備或模擬器。
      三、monkeyrunner的測試類型
      1、多設備控制:monkeyrunner API可以跨多個設備或模擬器實施測試套件。您可以在同一時間接上所有的設備或一次啟動全部模擬器(或統統一起),依據程序依次連接到每一個,然后運行一個或多個測試。您也可以用程序啟動一個配置好的模擬器,運行一個或多個測試,然后關閉模擬器。
      2、 功能測試: monkeyrunner可以為一個應用自動貫徹一次功能測試。您提供按鍵或觸摸事件的輸入數值,然后觀察輸出結果的截屏。
      3、 回歸測試:monkeyrunner可以運行某個應用,并將其結果截屏與既定已知正確的結果截屏相比較,以此測試應用的穩定性。
      4、 可擴展的自動化:由于monkeyrunner是一個API工具包,您可以基于Python模塊和程序開發一整套系統,以此來控制Android設備。除了使用monkeyrunner API之外,您還可以使用標準的Python os和subprocess模塊來調用Android Debug Bridge這樣的Android工具。
      四、運行monkeyrunner
      您可以直接使用一個代碼文件運行monkeyrunner,抑或在交互式對話中輸入monkeyrunner語句。不論使用哪種方式,您都需要調用SDK目錄的tools子目錄下的monkeyrunner命令。如果您提供一個文件名作為運行參數,則monkeyrunner將視文件內容為Python程序,并加以運行;否則,它將提供一個交互對話環境。
      monkeyrunner的命令語法為:
      monkeyrunner -plugin <plugin_jar> <program_filename> <program_options>
      五、實例
      以sample中的ApiDemos為例,先將其生成ApiDemos.apk。
      前提:已有device連接
      1、 將ApiDemos.apk放在$Android_Root\tools下。
      2、 在$Android_Root\tools下新建一個monkeyrunnerprogram.py文件,里面內容為:
    1 # Imports the monkeyrunner modules used by this program
    2
    3  from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
    4
    5  # Connects to the current device, returning a MonkeyDevice object
    6
    7 device = MonkeyRunner.waitForConnection()
    8
    9  # Installs the Android package. Notice that this method returns a boolean, so you can test
    10
    11  # to see if the installation worked.
    12
    13 device.installPackage('./ApiDemos.apk')
    14
    15
    16  # Runs the component
    17
    18 device.startActivity(component='com.example.android.apis/.ApiDemos')
    19
    20
    21  # Presses the Menu button
    22
    23 device.press('KEYCODE_MENU','DOWN_AND_UP')
    24
    25
    26  # Takes a screenshot
    27
    28 result = device.takeSnapshot()
    29
    30
    31  # Writes the screenshot to a file
    32
    33 result.writeToFile('./shot1.png','png')
     注意:SDK上的例子有些錯誤,不可直接復制,否則執行命令時會發生錯誤。具體可與我的上面這段代碼對照。
      3、 打開命令行轉到Android_Root\tools目錄下運行一下命令:
    monkeyrunner monkeyrunnerprogram.py
    110307 15:33:19.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:20.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:21.625:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: wake.
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice] Error starting command: monkey --port 12345
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]com.android.ddmlib.ShellCommandUnresponsiveException
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:408)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.ddmlib.Device.executeShellCommand(Device.java:276)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at com.android.monkeyrunner.adb.AdbMonkeyDevice$1.run(AdbMonkeyDevice.java:89)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.Executors$RunnableAdapter.call(UnknownSource)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.FutureTask.run(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.util.concurrent.ThreadPoolExecutor$Worker.run(UnknownSource)
    110307 15:33:22.718:S [pool-1-thread-1] [com.android.monkeyrunner.adb.AdbMonkeyDevice]  at java.lang.Thread.run(UnknownSource)
    110307 15:33:57.437:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: press KEYCODE_MENU.
    110307 15:33:59.171:I [main] [com.android.monkeyrunner.MonkeyManager] Monkey Command: quit.
      注:里面exception的提示我們可以忽略,因為我們可以看見 Monkey Command: press KEYCODE_MENU已經執行成功。
      4、 可以Android_Root\tools下查看生成的shot1.png的截圖。
      六、實例擴展
      因為ApiDemos首頁上按下MENU鍵沒有菜單出現,為了更加形象化,在實例五的基礎上繼續試驗:
      1、 在$Android_Root\tools下新建一個monkeyrunnerprogram1.py文件,里面內容為:
    1 # Imports the monkeyrunner modules used by this program
    2
    3  from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
    4
    5 # Connects to the current device, returning a MonkeyDevice object
    6
    7 device = MonkeyRunner.waitForConnection()
    8
    9 # Takes a screenshot
    10
    11 result = device.takeSnapshot()
    12
    13 # Writes the screenshot to a file
    14
    15 result.writeToFile('./shotbegin.png','png')
    16
    17 # Presses the Down button
    18
    19 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    20
    21 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    22
    23 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    24
    25 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    26
    27 device.press('KEYCODE_DPAD_DOWN','DOWN_AND_UP')
    28
    29 # Takes a screenshot
    30
    31 result = device.takeSnapshot()
    32
    33 # Writes the screenshot to a file
    34
    35 result.writeToFile('./shotend.png','png')
      2、  將畫面定位在Apidemos的首頁,并將光標定位在第一項上。
      3、  在$Android_Root\tools目錄下運行一下命令:
      monkeyrunner monkeyrunnerprogram1.py
      4、在運行過程中我們可以看見光標不斷向下移動,并且可以在當前目錄下我們自定義的截圖:
      運行前:
      運行后(做了五次下移操作):

    posted @ 2014-06-09 10:28 順其自然EVO 閱讀(163) | 評論 (0)編輯 收藏

    Sonar 代碼質量管理平臺

    1) 下載
      從sonar官網http://www.sonarsource.org/下載 (版本當然是最新的了)
      在官網上是不分系統的,一個zip包,下下來之后,包里包含 windows 、linux 和mac的版本
      2)解壓 執行
      我用的是 sonarqube-4.1
      解壓出這么一個文件夾后,打開bin/macosx-universal-64 ( 注: 我的系統是mac 64位的,所以選的這個目錄 )
      ./sonar.sh start
      出現下面字樣,說明運行成功
      Starting sonar...
      Started sonar.
      打開瀏覽器,http://localhost:9000 看一看,是不是出來了? 簡單吧。 當然這還沒完,還要配置一下數據庫
      3)配置數據庫
      我用的是mysql
      新建一個名為 sonar 的數據庫 ,注意編碼為utf8(庫名不喜歡的話,可以隨便改,要conf中對應上就可以  ),表就不需要管了。
      4) 修改配置文件
      位置 conf/sonar.properties
      主要就是修改 連接數據庫的用戶名、密碼、連接方式
      5)修改maven的配置文件 settings.xml
      添加以下內容:
    <profiles>
    <profile>
    <id>sonar</id>
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
    <!-- EXAMPLE FOR MYSQL -->
    <sonar.jdbc.url>
    jdbc:mysql://127.0.0.1:3306/sonar?characterEncoding=utf8&amp;useUnicode=true&amp;autoReconnect=true&amp;failOverReadOnly=false
    </sonar.jdbc.url>
    <sonar.jdbc.driverClassName>com.mysql.jdbc.Driver</sonar.jdbc.driverClassName>
    <sonar.jdbc.username>root</sonar.jdbc.username>
    <sonar.jdbc.password>******</sonar.jdbc.password>
    <!-- SERVER ON A REMOTE HOST -->
    <sonar.host.url>http://127.0.0.1:9000</sonar.host.url> <!-- 這個地址是你 sonar服務器的地址 -->
    </properties>
    </profile>
    </profiles>
      6) 基礎設施搭好了,開始測試
      進入你的項目運行:
      mvn clean install
      mvn sonar:sonar
      運行完之后,打開 localhost:9000 看一下吧,是不是倒進去了呢。
      7)問題
      如果出現問題,一定要耐心的解決,很簡單,都不是問題。

    posted @ 2014-06-09 10:18 順其自然EVO 閱讀(205) | 評論 (0)編輯 收藏

    僅列出標題
    共394頁: First 上一頁 102 103 104 105 106 107 108 109 110 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲国产精品成人| 成人午夜免费视频| 亚洲高清专区日韩精品| 国产成人精品免费视频大全五级| 99精品视频免费在线观看| 午夜免费国产体验区免费的| 亚洲啪AV永久无码精品放毛片| 亚洲av日韩av不卡在线观看| 亚洲国产中文字幕在线观看| 成人黄页网站免费观看大全| 1000部免费啪啪十八未年禁止观看 | 亚洲第一极品精品无码久久| 亚洲A丁香五香天堂网| 国内大片在线免费看| 中文字幕乱码免费视频| 99视频在线免费看| a毛片免费播放全部完整| 一级毛片无遮挡免费全部| 在线观看亚洲精品专区| 亚洲乱码无人区卡1卡2卡3| 亚洲一区二区三区免费视频 | 日本免费人成网ww555在线| 成人网站免费大全日韩国产| 免费观看又污又黄在线观看| 亚洲精品伦理熟女国产一区二区| 亚洲AV无码一区二区三区人 | 叮咚影视在线观看免费完整版| 久久久久久噜噜精品免费直播| 污视频网站免费在线观看| 精品久久亚洲一级α| 亚洲av日韩av永久无码电影| 亚洲色成人WWW永久在线观看| 亚洲色欲色欱wwW在线| 亚洲欧洲专线一区| 在线播放亚洲精品| 男女男精品网站免费观看| 黄色大片免费网站| 国产精品免费在线播放| 中出五十路免费视频| 玖玖在线免费视频| 18未年禁止免费观看|