<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/

    MATLAB中關于MySQL數據庫的操作

    首先要安裝mysql驅動程序包,詳細步驟如下:
      Step 1:將mysql-connector-java-5.1.7-bin.jar文件拷貝到......\MATLAB\R2009a\java\jar\toolbox
      Step 2:到......\MATLAB\R2009a\toolbox\local目錄下,找到classpath.txt文件,打開,并添加用來加載mysql的jdbc驅動語句:
      $matlabroot/java/jar/toolbox/mysql-connector-java-5.1.7-bin.jar
      Step 3:重新打開MATLAB即可
      驅動程序安裝成功后,接來下要是matlab連接mysql數據庫的代碼:
      conn=database('databasename','username','password','driver','databaseurl')
      連接成功后,返回連接對象。
      參數如下:
      *databasename: 數據庫名稱.
      *driver: JDBC driver.
      *username and password: 用戶名和密碼.
      *databaseurl: 類似于jdbc:subprotocol:subname. subprotocol是數據庫類型,
      subname類似于//hostname:port/databasename.
      如果matlab和數據庫建立了連接,將返回類似于如下信息:
    Instance: 'SampleDB'
    UserName: ''
    Driver: []
    URL: []
    Constructor: [1x1com.mathworks.toolbox.database.databaseConnect]
    Message: []
    Handle: [1x1 sun.jdbc.odbc.JdbcOdbcConnection]
    TimeOut: 0
    AutoCommit: 'off'
    Type: 'Database Object'
      連接mysql的代碼如下:
      conn = database('tissueppi','root','root','com.mysql.jdbc.Driver','jdbc:mysql://localhost:3306/tissueppi');
      連接成功后,就可以用exec函數執行sql語句
      exec函數執行sql語句并返回一個開指針
      語法如下:
      curs =exec(conn,'sqlquery')
      例如:curs = exec(conn, 'select * fromcustomers')
      執行完查詢后,還要將查詢結果從開放cursor對象導入到對象curs中,該功能是用
      cursor.fetch函數實現的。

    語法如下:
      curs =fetch(curs)
      使用curs.Data來顯示數據,curs.Data返回一個CELL結構,可以先把CELL結構轉換成
      MATRIX結構再取值:
      cur=cell2mat(cur)
      a=cur(1,1);
      則查詢結果就加到了向量a中
      注意:
      在exec函數執行查詢過程中,有的sql語句要輸入變量,這時可使用strcat函數完成該
      功能。
    t =strcat(s1, s2, s3, ...)
    for(t=1:10)
    sql1 = strcat('select count(did) from rss_genepairs_u wheregocc>=',num2str(t),' || gomf>= ',num2str(t),' || gobp >=',num2str(t));
    end
      完整代碼如下:
    conn =database('tissueppi','root','root','com.mysql.jdbc.Driver','jdbc:mysql://localhost:3306/tissueppi');
    for t=0.5:0.01:0.91
    for x=0.5:0.1:11
    sql = strcat('select count(did) from rss_genepairs_x2 where score<=',num2str(x),' and did in(select did fromrss_genepairs_u where gocc >=',num2str(t),' || gomf>= ',num2str(t),' || gobp >=',num2str(t),')');
    aTemp = exec(conn,sql);
    aTemp = fetch(aTemp);
    a = aTemp.Data;
    a = cell2mat(a);
    a= a(1,1);
    end
    end

    posted @ 2014-05-08 16:49 順其自然EVO 閱讀(2297) | 評論 (0)編輯 收藏

    用Asp.net還原與恢復sqlserver數據庫

    上次做了個項目,涉及到數據庫的還原和恢復,到網上找了一下,是利用SQLDMO實現的,只要添加SQLDMO引用就好了,然后利用下邊的類的方法就可以實現了。
      我把原作者的類擴充了一下,可以自動識別web.config里 的數據庫連接字符串,可以通過變量設置還原恢復的信息。
      需要注意的時還原,還原的時候問題最大了,有別的用戶使用數據庫的時候無法還原,解決辦法就是在MASTER數據庫中添加一個存儲過程:
    createprockillspid(@dbnamevarchar(20))
    as
    begin
    declare@sqlnvarchar(500)
    declare@spidint
    set@sql='declaregetspidcursorfor
    selectspidfromsysprocesseswheredbid=db_id('''+@dbname+''')'
    exec(@sql)
    opengetspid
    fetchnextfromgetspidinto@spid
    while@@fetch_status<>-1
    begin
    exec('kill'+@spid)
    fetchnextfromgetspidinto@spid
    end
    closegetspid
    deallocategetspid
    end
    GO
      在還原之前先執行這個存儲過程,需要傳遞dbname,就是你的數據庫的名字。下邊是類的原代碼:(web.config里的數據庫連接字符串是constr)
    using System;
    using System.Configuration;
    using System.Data.SqlClient;
    using System.Data;
    namespace web.base_class
    {
    /// <summary>
    /// DbOper類,主要應用SQLDMO實現對Microsoft SQL Server數據庫的備份和恢復
    /// </summary>
    public class DbOper
    {
    private string server;
    private string uid;
    private string pwd;
    private string database;
    private string conn;
    /// <summary>
    /// DbOper類的構造函數
    /// </summary>
    public DbOper()
    {
    conn=System.Configuration.ConfigurationSettings.AppSettings["constr"].ToString();
    server=cut(conn,"server=",";");
    uid=cut(conn,"uid=",";");
    pwd=cut(conn,"pwd=",";");
    database=cut(conn,"database=",";");
    }
    public string cut(string str,string bg,string ed)
    {
    string sub;
    sub=str.Substring(str.IndexOf(bg)+bg.Length);
    sub=sub.Substring(0,sub.IndexOf(";"));
    return sub;
    }
    /// <summary>
    /// 數據庫備份
    /// </summary>
    public  bool DbBackup(string url)
    {
    SQLDMO.Backup oBackup = new SQLDMO.BackupClass();
    SQLDMO.SQLServer oSQLServer = new SQLDMO.SQLServerClass();
    try
    {
    oSQLServer.LoginSecure = false;
    oSQLServer.Connect(server,uid, pwd);
    oBackup.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
    oBackup.Database = database;
    oBackup.Files = url;//"d:/Northwind.bak";
    oBackup.BackupSetName = database;
    oBackup.BackupSetDescription = "數據庫備份";
    oBackup.Initialize = true;
    oBackup.SQLBackup(oSQLServer);
    return true;
    }
    catch
    {
    return false;
    throw;
    }
    finally
    {
    oSQLServer.DisConnect();
    }
    }
    /// <summary>
    /// 數據庫恢復
    /// </summary>
    public string DbRestore(string url)
    {
    if(exepro()!=true)//執行存儲過程
    {
    return "操作失敗";
    }
    else
    {
    SQLDMO.Restore oRestore = new SQLDMO.RestoreClass();
    SQLDMO.SQLServer oSQLServer = new SQLDMO.SQLServerClass();
    try
    {
    oSQLServer.LoginSecure = false;
    oSQLServer.Connect(server, uid, pwd);
    oRestore.Action = SQLDMO.SQLDMO_RESTORE_TYPE.SQLDMORestore_Database;
    oRestore.Database = database;
    oRestore.Files = url;//@"d:/Northwind.bak";
    oRestore.FileNumber = 1;
    oRestore.ReplaceDatabase = true;
    oRestore.SQLRestore(oSQLServer);
    return "ok";
    }
    catch(Exception e)
    {
    return "恢復數據庫失敗";
    throw;
    }
    finally
    {
    oSQLServer.DisConnect();
    }
    }
    }
    private bool exepro()
    {
    SqlConnection conn1 = new SqlConnection("server="+server+";uid="+uid+";pwd="+pwd+";database=master");
    SqlCommand cmd = new SqlCommand("killspid",conn1);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@dbname","port");
    try
    {
    conn1.Open();
    cmd.ExecuteNonQuery();
    return true;
    }
    catch(Exception ex)
    {
    return false;
    }
    finally
    {
    conn1.Close();
    }
    }
    }
    }

    posted @ 2014-05-08 16:47 順其自然EVO 閱讀(136) | 評論 (0)編輯 收藏

    oracle數據庫備份

    1. 文件查看
      數據文件、控制文件、日志文件查看如下:
      select file#, status, enabled, name from V$datafile;--查看數據文件
      select * from v$controlfile;--控制文件
      select * from v$logfile;--日志文件
      2. 三種備份方法
      1)導入/導出(import/export)
      1.支持類型: table, user, tablespace, full database
      2. 導入導出例子:
    exp system/manager@TEST file=d:\export.dmp full=y--將數據庫TEST完全導出(全庫備份),用戶名system 密碼manager 導出到D:\daochu.dmp中
    exp system/manager@TEST file=d:\export.dmp owner=(system,sys)--將system和sys的表導出
    exp aichannel/aichannel@TEST file= d:export.dmp tables= (tab1,tab2)--將tab1表和tab2表導出
    imp system/manager@TEST file=d:\export.dmp tables=(tab1,tab2);--將export.dmp中tab1表和tab2表導入
    imp system/manager@TEST file=d:\export.dmp;
      3. 注意:若用戶權限不夠時需要修改權限
      --先以system/manager登錄
      --授予權限
      grant exp_full_database, imp_full_database to username;
      2)冷備份(非歸檔模式)
      1. 步驟:shutdown數據庫---> copy文件---> start數據庫
      2.  例子:
    connect tigger/sccot as sysdba;
    shutdown immediate;
    cp d:/test*.dbf d:export   --cp 文件  目標文件夾    數據文件
    cp d:/test*.ctl d:export   --控制文件
    cp d:/test*.log d:export   --日志文件
    startup;
      3)熱備份(歸檔模式)
      1. 說明:前提條件是數據庫運行在歸檔模式(oracle數據庫安裝默認運行在非歸檔模式)
      2. 將數據庫轉換為歸檔模式如下:(注意數據庫必須已裝載到此實例并且不在任何實例中打開)
      --需先關閉數據庫并加載數據庫
    shutdown immediate;
    startup mount;--(startup nomount 啟動實例;startup mount 啟動實例加載數據庫; startup 啟動實例加載數據庫打開數據庫)
    alter database archivelog;--數據庫必須已裝載到此實例并且不在任何實例中打開
      3. 歸檔相關操作
    archive log list;--查看是否出于歸檔模式;
    alter system set log_archive_start =true scope =spfile; --啟用主動歸檔
    select name from v$archived_log; --查詢歸檔日志
    alter system set log_achive_start=false scope=spfile;--將數據庫切換為歸檔模式
    archive log stop;
    archive log start;
    4. 熱備份具體步驟如下:
    shutdown immediate;
    startup mount;
    alter database archivelog;
    alter database open;
    alter tablespace users begin backup; --設置備份模式;
    host copy d:\oracle\*.dbf d:\export;--拷貝
    alter tablespace users end backup ;--結束備份狀態
    alter system switch logfile--切換日志,使用當前日志歸檔
      5. 不足之處:不能出錯
      6. 優點:備份時數據庫仍然可以使用,備份時間短
      3.RMAN備份和恢復工具(rocovery manager)
      1)說明:
      1.RMAN是 ORACLE提供的一個備份與恢復的工具,可以用來執行完全或不完全的數據庫恢復。
      2.RMAN不能用于備份初始化參數文件和口令文件。
      3. 與傳統工具相比,RMAN具有獨特的優勢:跳過未使用的數據塊。當備份一個RMAN備份集時,RMAN不會備份從未被寫入的數據塊,而傳統的方式無法獲知那些是未被使用的數據塊。
      4. RMAN可以進行增量備份(增量備份是針對于上一次備份(無論是哪種備份):備份上一次備份后,所有發生變化的文件)
      2)例子:
      --準備工作:
      connect tiger/sccot;
      startup mount
      alter database archivelog
      alter database open
      --查看備份相關信息
      list backupset;
      --備份全庫
      backup database;
      --備份表空間
      backup tablespace tp1;
      --備份全庫刪除舊的歸檔日志
      backup databse plus archivelog delete input;--備份全庫及控制文件、服務器參數文件與所有歸檔的重做日志,并刪除舊的歸檔日志
      --備份表空間刪除舊的歸檔日志
      backup tablespace system plus archivelog delete input;
      --備份歸檔日志
      backup archivelog all delete input;
      --查看備份信息
      list of backup sets;
      --0增量備份(等于全備份)
      backup incremental level=0(level 0) database;
      --1級增量備份
      backup incremental level 1 database;
      注意:0級增量備份和完全備份唯一的區別,0級增量備份能作為增量備份的基礎,而全備份不能作為增量備份的基礎

    posted @ 2014-05-08 16:47 順其自然EVO 閱讀(209) | 評論 (0)編輯 收藏

    淺談Java中的對象和對象引用

     在Java中,有一組名詞經常一起出現,它們就是“對象和對象引用”,很多朋友在初學Java的時候可能經常會混淆這2個概念,覺得它們是一回事,事實上則不然。今天我們就來一起了解一下對象和對象引用之間的區別和聯系。
      1.何謂對象?
      在Java中有一句比較流行的話,叫做“萬物皆對象”,這是Java語言設計之初的理念之一。要理解什么是對象,需要跟類一起結合起來理解。下面這段話引自《Java編程思想》中的一段原話:
      “按照通俗的說法,每個對象都是某個類(class)的一個實例(instance),這里,‘類’就是‘類型’的同義詞。”
      從這一句話就可以理解到對象的本質,簡而言之,它就是類的實例,比如所有的人統稱為“人類”,這里的“人類”就是一個類(物種的一種類型),而具體到每個人,比如張三這個人,它就是對象,就是“人類”的實例。
      2.何謂對象引用?
      我們先看一段話:
      “每種編程語言都有自己的數據處理方式。有些時候,程序員必須注意將要處理的數據是什么類型。你是直接操縱元素,還是用某種基于特殊語法的間接表示(例如C/C++里的指針)來操作對象。所有這些在 Java 里都得到了簡化,一切都被視為對象。因此,我們可采用一種統一的語法。盡管將一切都“看作”對象,但操縱的標識符實際是指向一個對象的“引用”(reference)。”
      這段話來自于《Java編程思想》,很顯然,從這段話可以看出對象和對象引用不是一回事,是兩個完全不同的概念。舉個例子,我們通常會用下面這一行代碼來創建一個對象:
      Person person = new Person("張三");
      有人會說,這里的person是一個對象,是Person類的一個實例。
      也有人會說,這里的person并不是真正的對象,而是指向所創建的對象的引用。
      到底哪種說法是對的?我們先不急著糾結哪種說法是對的,再看兩行代碼:
      Person person;
      person = new Person("張三");
      這兩行代碼實現的功能和上面的一行代碼是完全一樣的。大家都知道,在Java中new是用來在堆上創建對象用的,如果person是一個對象的話,那么第二行為何還要通過new來創建對象呢?由此可見,person并不是所創建的對象,是什么?上面的一段話說的很清楚,“操縱的標識符實際是指向一個對象的引用”,也就是說person是一個引用,是指向一個可以指向Person類的對象的引用。真正創建對象的語句是右邊的new Person("張三");
      再看一個例子:
      Person person;
      person = new Person("張三");
      person = new Person("李四");
      這里讓person先指向了“張三”這個對象,然后又指向了“李四”這個對象。也就是說,Person person,這句話只是聲明了一個Person類的引用,它可以指向任何Person類的實例。這個道理就和下面這段代碼一樣:
      int a;
      a=2;
      a=3;
      這里先聲明了一個int類型的變量a,先對a賦值為2,后面又賦值為3.也就是說int類型的變量a,可以讓它的值為2,也可以為3,只要是合法的int類型的數值即可。
      也就是說,一個引用可以指向多個對象,而一個對象可不可以被多個引用所指呢?答案當然是可以的。
      比如:
      Person person1 = new Person("張三");
      Person person2 = person1;
      person1和person2都指向了“張三”這個對象。
      關于對象和對象引用的區別和聯系暫時就講這么多了,感興趣的朋友可以查閱相關文檔和資料。

    posted @ 2014-05-08 16:46 順其自然EVO 閱讀(130) | 評論 (0)編輯 收藏

    淺談Java中的對象和對象引用

     在Java中,有一組名詞經常一起出現,它們就是“對象和對象引用”,很多朋友在初學Java的時候可能經常會混淆這2個概念,覺得它們是一回事,事實上則不然。今天我們就來一起了解一下對象和對象引用之間的區別和聯系。
      1.何謂對象?
      在Java中有一句比較流行的話,叫做“萬物皆對象”,這是Java語言設計之初的理念之一。要理解什么是對象,需要跟類一起結合起來理解。下面這段話引自《Java編程思想》中的一段原話:
      “按照通俗的說法,每個對象都是某個類(class)的一個實例(instance),這里,‘類’就是‘類型’的同義詞。”
      從這一句話就可以理解到對象的本質,簡而言之,它就是類的實例,比如所有的人統稱為“人類”,這里的“人類”就是一個類(物種的一種類型),而具體到每個人,比如張三這個人,它就是對象,就是“人類”的實例。
      2.何謂對象引用?
      我們先看一段話:
      “每種編程語言都有自己的數據處理方式。有些時候,程序員必須注意將要處理的數據是什么類型。你是直接操縱元素,還是用某種基于特殊語法的間接表示(例如C/C++里的指針)來操作對象。所有這些在 Java 里都得到了簡化,一切都被視為對象。因此,我們可采用一種統一的語法。盡管將一切都“看作”對象,但操縱的標識符實際是指向一個對象的“引用”(reference)。”
      這段話來自于《Java編程思想》,很顯然,從這段話可以看出對象和對象引用不是一回事,是兩個完全不同的概念。舉個例子,我們通常會用下面這一行代碼來創建一個對象:
      Person person = new Person("張三");
      有人會說,這里的person是一個對象,是Person類的一個實例。
      也有人會說,這里的person并不是真正的對象,而是指向所創建的對象的引用。
      到底哪種說法是對的?我們先不急著糾結哪種說法是對的,再看兩行代碼:
      Person person;
      person = new Person("張三");
      這兩行代碼實現的功能和上面的一行代碼是完全一樣的。大家都知道,在Java中new是用來在堆上創建對象用的,如果person是一個對象的話,那么第二行為何還要通過new來創建對象呢?由此可見,person并不是所創建的對象,是什么?上面的一段話說的很清楚,“操縱的標識符實際是指向一個對象的引用”,也就是說person是一個引用,是指向一個可以指向Person類的對象的引用。真正創建對象的語句是右邊的new Person("張三");
      再看一個例子:
      Person person;
      person = new Person("張三");
      person = new Person("李四");
      這里讓person先指向了“張三”這個對象,然后又指向了“李四”這個對象。也就是說,Person person,這句話只是聲明了一個Person類的引用,它可以指向任何Person類的實例。這個道理就和下面這段代碼一樣:
      int a;
      a=2;
      a=3;
      這里先聲明了一個int類型的變量a,先對a賦值為2,后面又賦值為3.也就是說int類型的變量a,可以讓它的值為2,也可以為3,只要是合法的int類型的數值即可。
      也就是說,一個引用可以指向多個對象,而一個對象可不可以被多個引用所指呢?答案當然是可以的。
      比如:
      Person person1 = new Person("張三");
      Person person2 = person1;
      person1和person2都指向了“張三”這個對象。
      關于對象和對象引用的區別和聯系暫時就講這么多了,感興趣的朋友可以查閱相關文檔和資料。

    posted @ 2014-05-08 16:46 順其自然EVO 閱讀(125) | 評論 (0)編輯 收藏

    企業級軟件開發需要什么樣的框架?

     1)領域建模
      分析領域特定的問題。比如趕集網這一分類信息網站,她的定位是解決都市人尋求房屋出租、二手房、二手車、二手物品交易、求職招聘等生活信息的需求的。在領域建模階段要解決的就是這個軟件的定位問題,做什么不做什么。這一階段由高層領導,市場銷售及系統分析師等完成。
      2) 平臺技術選擇
      技術選型,比如用什么平臺/架構(.net,j2ee,php,python等等)開發,采用什么服務器托管等。這一階段由系統高層領導,系統分析師及系統架構師等完成。
      3) 解決方案
      根據選定的平臺技術等給出一個可行的解決方案,說明系統會使用什么樣的部署結構等。這一階段由系統分析師及系統架構師等完成。
      4) 需求分析
      市場技術的可行性已經確定,接下來就是把做什么具體化了。把每一個功能模塊及非功能性需求羅列出來。這一階段由市場銷售,系統分析師,產品經理,用戶體驗師,測試工程師等完成。
      5) 技術實現
      需求已經明確,接下來就是設計與實現了。除了實現系統的特定功能外,我們還要實現系統用戶的驗證與授權,系統日志與異常處理,發郵件與用戶交互等。這一部分就是企業級軟件開發中可以復用的切入點,也是和我們系統架構師,軟件工程師的工作密切相關的部分。這一階段由系統架構師,開發經理,軟件工程師等完成。
      6)集成測試
      在預設的軟硬件環境下,測試系統是否很好地滿足了用戶的需求。
      這一階段由軟件工程師,測試工程師等完成。
      7) 驗收測試
      將系統交由用戶或用戶代表使用。可能會根據反饋進行一定的修改等。這一階段由產品經理,用戶或用戶代表,軟件工程師,測試工程師等完成。
      8)交付
      實際交給用戶運營與使用。這一階段由市場銷售,技術代表,用戶等完成。
      9) 維護
      根據用戶實際使用中給出的反饋或提出的新需求等修改系統。
      這一階段幾乎是上面1-8的迭代過程。
      什么是框架?
      一個框架是在一個給定的問題領域內,一個應用程序的一部分設計與實現。
      框架中要包含什么?
      框架中應該提供通用的功能與實現,比如用戶驗證與授權,日志與異常處理,緩存策略與實現,發送郵件,定時數據處理(Jobs),數據訪問策略與實現,多語言支持,通用UI組件等。
      為什么要開發框架?
      較大的軟件開發公司都有自己的框架,因為框架中積累了很多通用的功能,可以直接復用。采用框架可以規范開發人員的設計與代碼,有利于在一個項目內多人協同工作,一致性好,可維護性好。這樣就可以提高質量,縮短開發周期,進而也就提高了生產率,降低了開發費用。
      我如何做框架?
      我的經驗告訴我,開發框架一定要遵循簡單封裝,決不能過度設計。

    posted @ 2014-05-08 16:45 順其自然EVO 閱讀(219) | 評論 (0)編輯 收藏

    再解Java中的String

    今天朋友問我String的內容是真的不可變嗎?我肯定告訴他是的?因為在我的主觀意識里String就是一個不可變的對象。于是他給我發了這段程序:
    public class StringTest {
    public static void main(String[] args) throws Exception {
    String a = "chenssy";
    System.out.println("a = " + a);
    Field a_ = String.class.getDeclaredField("value");
    a.setAccessible(true);
    char[] value=(char[])a.get(a);
    value[4]='_';   //修改a所指向的值
    System.out.println("a = " + a);
    }
    }
      看到這個簡單的程序,我笑了,你這不是從底層來修改String的值么?從這里來理解String的值肯定是可以改變的啦(我們應該始終相信String的不可變性)!接著他再給我一段程序:
    public class StringTest {
    public static void main(String[] args) throws Exception {
    String a = "chenssy";
    String b = "chenssy";
    String c = new String("chenssy");
    System.out.println("--------------修改前值-------------------");
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + c);
    //修改String的值
    Field a_ = String.class.getDeclaredField("value");
    a_.setAccessible(true);
    char[] value=(char[])a_.get(a);
    value[4]='_';   //修改a所指向的值
    System.out.println("--------------修改后值-------------------");
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("chenssy");
    System.out.println("c = " + c);
    }
    }

    字體:        | 上一篇 下一篇 | 打印  | 我要投稿 

      乍看這程序是異常的簡單,無非就是賦值、改值、輸出嘛!可能你現在就會毫不猶豫的說太簡單了結果就是……。但是!!你的毫不猶豫會害死你,而且你的結果很可能錯誤。那么運行結果是什么呢?
    --------------修改前值-------------------
    a = chenssy
    b = chenssy
    c = chenssy
    --------------修改后值-------------------
    a = chen_sy
    b = chen_sy
    chen_sy
    c = chen_ssy
      修改前值很容易理解,但是修改后值呢?是不是有點兒不理解呢?你可能會問:為什么System.out.println("chenssy");的結果會是chen_ssy,System.out.println("c = " + c);也是chen_ssy呢?
      要明白這個其實也比較簡單,掌握一個知識點:字符串常量池。
      我們知道字符串的分配和其他對象分配一樣,是需要消耗高昂的時間和空間的,而且字符串我們使用的非常多。JVM為了提高性能和減少內存的開銷,在實例化字符串的時候進行了一些優化:使用字符串常量池。每當我們創建字符串常量時,JVM會首先檢查字符串常量池,如果該字符串已經存在常量池中,那么就直接返回常量池中的實例引用。如果字符串不存在常量池中,就會實例化該字符串并且將其放到常量池中。由于String字符串的不可變性我們可以十分肯定常量池中一定不存在兩個相同的字符串(這點對理解上面至關重要)。
      我們再來理解上面的程序。
      String a = "chenssy";
      String b = "chenssy";
      a、b和字面上的chenssy都是指向JVM字符串常量池中的”chenssy”對象,他們指向同一個對象。
      String c = new String("chenssy");
      new關鍵字一定會產生一個對象chenssy(注意這個chenssy和上面的chenssy不同),同時這個對象是存儲在堆中。所以上面應該產生了兩個對象:保存在棧中的c和保存堆中chenssy。但是在Java中根本就不存在兩個完全一模一樣的字符串對象。故堆中的chenssy應該是引用字符串常量池中chenssy。所以c、chenssy、池chenssy的關系應該是:c--->chenssy--->池chenssy。整個關系如下:
      通過上面的圖我們可以非常清晰的認識他們之間的關系。所以我們修改內存中的值,他變化的是所有。
      總結:雖然a、b、c、chenssy是不同的對象,但是從String的內部結構我們是可以理解上面的。String c = new String("chenssy");雖然c的內容是創建在堆中,但是他的內部value還是指向JVM常量池的chenssy的value,它構造chenssy時所用的參數依然是chenssy字符串常量。

    posted @ 2014-05-08 16:45 順其自然EVO 閱讀(184) | 評論 (0)編輯 收藏

    Appium IOS 自動化測試初探

     手機平臺的自動化測試工具很多,之前研究過了安卓和蘋果的原生自動化測試框架,經一些同事介紹,貌似Appium是個不錯的工具。
      想記錄一下研究的結果,也算是篇干貨的文章
      在網上也看了一些視頻,個人認為這個自動化測試的特點就是
      1. 多編程語言支持
      相對于傳統的IOS UIautomation只能支持js語言,Appium起到了一個翻譯的作用,它其實是一個CS架構,服務器和IOS模擬器或真機直接通訊,客戶端和服務器之間用HTTP協議進行交互,所以客戶端用什么語言其實不重要。下面會有一個python編程的實際例子。
      2. 遠程測試支持
      正如上面說的,客戶端和服務器之間用HTTP協議通訊,那么也就是說,客戶端可以和服務器在同一臺機器或者不同的機器。
      3. 較好的錄制功能
      Appium提供了一個很好的錄制工具,可以讓程序員一步一步的把步驟進行精確的錄制
      4. 單步調試
      程序員可以利用高級腳本語言,比如Python對被測程序進行單步調試,比如一條命令對應一個UI動作
      如何使用appium,基于2014年5月份發布的appium 1.0來說,大約是這樣的,
      你必須要有xcode進行自動化測試的基礎,如果沒有的話,請先補習
      A. 如果是模擬器測試
      1. 選擇應用安裝包的位置
      2. 再選擇期望的模擬器平臺,IOS版本,再點Launch就可以了
      3. Launch之后會發現什么都沒有,其實Appium已經運行了,請注意運行的窗口中有沒有錯誤
      4. 下面就是錄測試用例,點擊一個藍色的底,白色的i的按鈕
      5. 過一段時間后就會出現inspector的窗口
      6. 下面是一個例子,比如我要點一個按鈕,
      6.1 首先現在左邊的樹形窗口里面找到一個按鈕的位置,有點類似Firebug找網頁控件
      6.2 然后在下面的動作框選擇你想要的動作,點擊就是Tap,然后你會發現這個按鈕真的被點擊了(這是一個單步調試很直觀的例子)


     7. 如何把錄制變成腳本
      7.1 首先要點擊inspector窗口的Record按鈕
      7.2 選擇你需要的編程語言
      7.3 再繼續重復你需要做的UI操作
      7.4 最后就是把代碼拷貝出去
      8. 如何重錄測試
      8.1 關掉inspector,
      8.2 代碼需要稍微的修改,Python的代碼錄出來居然有語法錯誤,這里給個例子,對照看就好了(當然必要的python庫必須安裝)
    from selenium.webdriver.firefox.webdriver import WebDriver
    from selenium.webdriver.common.action_chains import ActionChains
    import time
    import os
    import selenium
    success = True
    desired_caps = {}
    desired_caps['browserName'] = 'iOS'
    desired_caps['platform'] = 'Mac'
    desired_caps['version'] = '6.1'
    desired_caps['device'] = 'iPad'
    desired_caps['app'] = os.path.abspath('/Users/marshall/Library/Developer/Xcode/DerivedData/TestAutomation-empzzpwyyxctxidnwdsrtlssueqi/Build/Products/Debug-iphonesimulator/TestAutomation.app')
    wd = selenium.webdriver.Remote('http://0.0.0.0:4723/wd/hub', desired_caps)
    wd.implicitly_wait(60)
    def is_alert_present(wd):
    try:
    wd.switch_to_alert().text
    return True
    except:
    return False
    try:
    wd.find_element_by_name("First").click()
    wd.find_element_by_name("Second").click()
    finally:
    wd.quit()
    if not success:
    raise Exception("Test failed.")
      8.3 運行代碼,查看測試結果
      B. 如果是真機測試
      真機測試其實遇到了些問題,我大概說一下我的步驟
      1. 配置應用的BundleID和設備的UDID
      BundleID不知道怎么看的請用itools
      UDID不知道怎么找的請用iTunes或itools
      應用必須是你自己的開發者賬號簽名過的
      2. Launch Appium
      3. 點擊inspector的按鈕,接下來應用會顯示在iPad上,但是過一會就會閃退(我試了好幾個應用都有這個問題),我已經給Appium報告了一個bug,看看會不會有回復吧。
      如果有人在真機上成功使用inspector的,也請留言分享一下

    posted @ 2014-05-08 16:42 順其自然EVO 閱讀(16022) | 評論 (1)編輯 收藏

    巧用工具洞察用戶行為

     冬夜的被窩里、飛馳狂奔的公車上、無聊乏味的課堂中掏出手機,打開手機QQ的閱讀中心,翻開一本書看看不失為好的消遣方式,手機QQ除了提供好的閱讀內容供用戶消遣,用戶研究人員和設計師也非常關心如何給用戶帶來好的閱讀翻頁操作體驗,減少用戶的翻頁誤操作情況,因此針對手機QQ4.5版的閱讀中心用戶翻頁熱區操作展開了一場測試
      研究目的
      目前手機QQ的新手引導圖(測試時在用的是引導圖一)是否會對用戶操作有引導效果;
      跟蹤用戶在閱讀過程中翻頁(翻上一頁、翻下一頁和出菜單)操作的熱區。
      實驗設計
      按照用戶是否有手機閱讀經驗分為新手用戶(20人)和老手用戶(20人),不同類型的用戶均隨機分為看引導圖的用戶和不看引導圖的用戶,測試的引導圖除了當時在用的引導圖一外,還包括備用的兩張引導圖,分別為下面的引導圖二和引導圖三。
      工具準備
      目前比較高端的眼動儀也只是記錄用戶眼睛的瀏覽軌跡,但是要記錄用戶在閱讀過程中的操作軌跡,目前還沒有,要開發在用戶的閱讀頁面埋點在操作上也不現實,于是想到了市面上的一些好的畫圖軟件,用戶的操作過程可以通過畫筆在隱藏的圖層記錄下來,但用戶在操作過程中全然不知,最后在網上找到了兩款比較好的畫圖軟件,蘋果端是 ArtStudio Lite,安卓端是SketchBook Mobile 。
      測試任務安排
      萬事俱備,只欠用戶,邀約來的用戶中必須包括有手機閱讀經驗和無手機閱讀經驗的用戶,隨機截取書本的某三頁的圖片,如下:
      用戶來了之后,按手機類型安裝好畫圖軟件,同時將書本頁面導入到已經安裝到用戶手機里的畫圖軟件中,在測試過程中不同的翻頁操作使用不同的書本頁面(為了后期統計方便),以iPhone端的ArtStudio Lite為例,操作如下:
      正式測試
      測試具體過程不詳述,有幾點心得與大家分享:
      盡量用用戶自己的手機并強調用戶讓自己最習慣和自然的常用持機方式操作;
      每種操作對應一個測試圖片,有利于后期數據整理;
      看引導圖時控制時間,以防用戶強行記憶,同時對引導圖不做任何解釋;
      每位用戶的每種操作至少要有三次且每種操作的次序隨機;
      適當的時候用一定的技巧掩蓋來回切換圖片(“不怎么靈敏,多翻幾次”,“我看看是怎么回事”);
      PS:盡量不要讓用戶發現我們在記錄他的操作軌跡,但是如果萬一被用戶發現,那就告訴用戶測試是用來干什么,讓用戶用最自然的狀態去操作 。
     測試結果
      下圖是軟件記錄的用戶分別翻下一頁、出菜單和翻上一頁的操作軌跡。
      將這些圖片導入到photoshop,找到用戶每次操作的起點坐標,錄入到excel中。
      研究結論
      看過引導圖二的用戶在“上一頁、出菜單和下一頁”的操作上更集中。
      有小伙伴肯定會問,引導圖對用戶的翻頁操作有效果就可以了,可是從實際觀察用戶的使用行為來看,用戶容易忽略并錯過引導圖,因此設計中需要考慮到沒有接收到引導圖信息用戶的操作習慣。
      寫在后面的話
      隨風潛入夜,潤物細無聲,作為一名用戶研究人員,功力練就的最高境界就是希望能像詩中表達的意境,潛入并洞悉用戶的內心,雖實際操作有一定難度,但工欲善其事,必先利其器,如果能手握利器,則可以在一定程度上做到,所謂的利器不一定是高大上的東西,小東西一樣能做大事,身在設計部門,對一些常用軟件也應保持一定的關注度,關鍵時候能拿來為我所用。
      結合本項目,在測試過程中由于還是有一些小的干預在里面,比如在操作過程中要切換圖片,有了本次項目的經驗,后續將加入開發的力量,做成專門的測試軟件,記錄用戶的操作路徑,實現工具的升級并用于以后類似的操作類基礎性研究測試。

    posted @ 2014-05-08 16:41 順其自然EVO 閱讀(155) | 評論 (0)編輯 收藏

    關于統一等價類劃分的術語和過程

    關于統一等價類劃分的術語和過程
        等價類劃分是很重要的軟件測試設計技術之一。重要到幾乎每一個測試員都要用到這項技術,他們中的一些人甚至還沒有意識到被這他們稱為 “常識”的實際上是一項正式的技術。
    但不知何故,作為一個測試團隊,我們就等價類劃分的過程這一點上似乎無法達成一致意見。甚至連它的術語都意見不一。劃分和類是同一回事嗎?等級劃分的有效和無效意味著什么?當我們了解什么是類之后,又該如何把它運用到測試用例中呢?我們需要輸出劃分嗎?在這篇文章里,我會提出一個關于統一等價類劃分的術語的建議,并努力找出一個單一的方法來得到測試用例。我匯總了許多測試專家的知識見解并且找出其中的共同點,努力做到不遭到一絲質疑地去除這些不統一。

    來源
        參考咨詢了多方來源,我匯集了關于等價類劃分技術的信息,大多數作者都偏向Glenford Myers [1]和Boris Beizer [2]的觀點。并不是所有的關于等價類劃分技術的信息來源都描述了整個過程,也不是所有的都描述了同一個過程。最實用的關于怎樣運用這項技術的信息是由Erik van Veenendaal [6]和Edward Kit [3]所描述的。

    術語
    零星碎片
        在等價類劃分里,我們取輸入一個電腦程序的內容,把它切成零星碎片,這本應由該程序自己以同樣的方法處理的。
    不同的來源里用不同的術語來描述這些碎片:
    · Myers [1]認為: “等價類劃分是通過考慮了每一種輸入條件...確認的,并把它分成兩至更多份以上。
    · Black [9]:“等價類,也叫做等價分區。”
    · Van Veenendaal [6]:“......等價類或者劃分區......”
    · De Grood [10]:“......有效和無效的等價類別......”
    讓我們看一看關于“劃分”的專業術語的準確的起源“set theory”。我是找不到我的舊教科書來看了,但是我可以參考維基百科,它是這樣寫的:“集合S的一個劃分P是兩兩不相交的非空子集,使得∪P = S。”,“集合S的任意一個分區P給S引入了一個等價關系,其中每個A∈P是就一個等價類。同樣地,給S引入一個等價關系,不同的等價類的集合就是S的分區。”
    我提議回歸最初,堅持在set theory中使用的準確的術語。
    從上面的準確的術語,我們學到了以下(下面是用簡單明了英語改寫了):
    ·劃分是把東西切碎。
    ·某物被切成零星碎片的方法就被稱為劃分。
    ·這些零星碎片被稱作類

        所以當我確定了整數1到10有兩種劃分時就意味著我可以用兩種方法把它們切碎,也就是,奇數和偶數(這是第一種劃分)或者質數和非質數(這是第二種)。把小于5的數和大于等于5的數分開會生成由兩個類構成的第三種劃分。

    有效和無效
        一旦一個程序的輸入范圍被劃分成等價類,我們就不得不在我們可以把它們與測試用例結合起來之前決出這些類里面哪些是有效的哪些是無效的。但是我們怎么定義“有效”?
    · Black [9]:“...有效類...描述有效的情況,系統需要正常處理...”
    · Van Veenendaal [6]:“等價類劃分下的無效數據并不是說這個數據是錯誤的;而是指這個數據不在具體的劃分范圍之內。”
    · Burnstein [7]:“…有效類…描述系統可以正常處理…的情況。”
    · Van Veenendaal [6]:“無效類表示輸入錯誤或異常”
    別人告訴過我:一個類,當程序不指定輸入來自該類時,它被認為是無效類。但是要是指定行為是一個錯誤信息,又該怎么辦?D.J. de Grood [10] 說:“…并不是一個無效值,因為這次輸入的錯誤處理已被具體…”。
    我建議采納和適應用于分類樹方法中的定義。“有效類描述被測試對象有條不紊地處理的輸入情況。無效類應該被測試對象引發錯誤處理反映。”這段引述的大部分都是和原文一樣的,我加了一個詞“應該”來覆蓋錯誤處理機制(還)不到位的情況,我還用“類”替代了Grochtmann [4]原話中的“測試用例”。

    食譜
    切片和切塊
        現在大家都清楚了什么是劃分(劃分的過程),什么是類(劃分結果)了,但還不明白輸入域是如何被劃分的。Van Veenendaal [6] 和Kit [3]就所有輸入和通常它們是如何被劃分做出了詳細準確的概括。但是劃分是一個測試員的工作嗎?劃分的基礎已經在測試員要求之中了。例:“6歲以下的兒童在至少一位家長的陪伴下可免費進入”。就是按兒童的年齡和陪同者的人數劃分免費的部分人群。但是我們必須確保顧客即要求工程師和軟件開發員都以同樣的方式來理解它。

    結合類
        現在我們已經解釋清楚了術語,我希望你們同意我做出的選擇,我們來說說結合類吧。
    等價類劃分中所提到的來源中有許多的觀點,所以再一次的,我們不得不作選擇。
        首先讓我們來看看軟件構件測試的標準– BS 7925-2 [5]。這個標準給我們提供了自由, “在生成測試用例時,可以采取兩種截然不同的方法。用第一種方法,一個測試用例在一對一的基礎上生成每一個確定的劃分區。用第二種方法,一組最小的測試用例生成并覆蓋了所有確定的劃分區。”請注意這句話中的“劃分區”一詞,我是提議用“類”的。
        大多數來源生成了覆蓋所有有效類的一組最小的測試用例。接下來看看Myers的方法:“寫一個測試用例,這個用例只覆蓋不被覆蓋的無效等價類之中的一個。”直到所有無效類都被覆蓋。不把多個無效輸入結合到一個測試用例中的理由Myers清楚地說明了,Kit and Veenendaal也這樣解釋到:“如果多個無效EC在同一個用例中被測試出來,一些測試可能無法執行,因為第一個測試可能會掩蓋其他測試或者終止執行測試用例。”但是一些人([6], [9])提出一個單一的,完全無效的測試用例可能是有用的。尤其是在Web應用程序中,輸入數據在被發送到服務器前經常先進入一個表格檢查其有效性。讓我為您展示以下幾種結合類的菜單:
    選擇1—低脂餐
    · 開胃小吃:一組最小的覆蓋所有有效類的測試用例
    · 主菜:一組最小的覆蓋所有無效類的測試用例
    · 飯后甜點:抱歉,沒有甜點

    選擇2—常規餐
    · 開胃小吃:一組最小的覆蓋所有有效類的測試用例
    · 主菜:一組測試用例,其中每一個用例每次只覆蓋一個單一的無效類,除非所有的無效類都被覆蓋(提供)了
    · 飯后甜點:抱歉,沒有甜點

    選擇3—豐盛餐
    · 開胃小吃:一組最小的覆蓋所有有效類的測試用例
    · 主菜:一組測試用例,其中每一個用例每次只覆蓋一個單一的無效類,除非所有的無效類都被覆蓋(提供)了
    · 飯后甜點:一個只覆蓋最好的無效類的單一測試用例

    選擇4—(幾乎)所有你能吃的
    · 開胃小吃:一組最小的覆蓋所有有效類的測試用例
    · 主菜:一組測試用例,其中每一個用例每次只覆蓋一個單一的無效類,除非所有的無效類都被覆蓋(提供)了
    · 飯后甜點:一組最小的覆蓋覆蓋所有無效類的完全無效的測試用例
    · 額外: 給極度饑餓的人,我們提供了精心挑選的覆蓋所有輸出類的額外的測試用例組合套餐

        我們該如何選擇呢?這個取決于我們對于測試之下的主題所知道什么。
        在低風險的情況下,你不是很餓的話,一組最小的測試用例或許是最好的選擇。像上面的網站的例子,如果我們知道該軟件是用來在開始一次計算前檢查在表單中的字段中所輸入的每個值的話,那么明智的做法就是添加額外的完全無效的測試案例。
        在高風險的情況下,我們想要確保每一個無效類被識別為無效并被視作無效來對待。所以我們至少需要一份不錯的常規餐或者“所有你能吃的”。
    但是額外呢?輸出劃分是有營養的一部分還是它只是讓你發胖的部分呢?
    另外,它還取決于實際情況和測試目標,當你在測試一個將輸入轉化為輸出的模塊(這經常發生),接著,該輸出被用作另一個模塊的輸入時,知道是否所有的可能輸出會因為正確的理由被接受或拒絕可能是相當有價值的。
        事實上,我們在這兒講的是集成測試。為了執行一個這樣的測試,必須生成接受模塊的所有的可能輸入類。因此,我們需要全面了解調用模塊的輸出。調用模塊的范圍必須符合被調用模塊的域。正如Beizer所說:“…調用者的范圍就是調用者對被調例程域的概念…”我們想證明這個觀念是正確的。

    posted @ 2014-05-08 16:41 順其自然EVO 閱讀(277) | 評論 (0)編輯 收藏

    僅列出標題
    共394頁: First 上一頁 115 116 117 118 119 120 121 122 123 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲高清最新av网站| 亚洲精品黄色视频在线观看免费资源 | 国产午夜无码精品免费看| 亚洲激情在线视频| 美女网站免费福利视频| 精品成人一区二区三区免费视频| 亚洲日韩人妻第一页| 84pao强力永久免费高清| 亚洲AV色欲色欲WWW| 亚洲精品卡2卡3卡4卡5卡区| 很黄很色很刺激的视频免费| 久久久久久免费一区二区三区 | 久久精品a一国产成人免费网站| 老司机午夜在线视频免费| 亚洲成AV人片在线观看无码 | 亚洲最新视频在线观看| 日本一道在线日本一道高清不卡免费| 思思久久99热免费精品6| 久久久亚洲裙底偷窥综合| 亚洲av无码国产精品色在线看不卡| 91频在线观看免费大全| 九九热久久免费视频| 2020天堂在线亚洲精品专区| 国产亚洲精品不卡在线| 免费毛片a在线观看67194| 日韩在线永久免费播放| 美女被爆羞羞网站在免费观看| 亚洲私人无码综合久久网| 亚洲国产精品第一区二区| 亚洲成AV人片一区二区| 亚洲女久久久噜噜噜熟女| 国产精品四虎在线观看免费| **真实毛片免费观看| 久久av免费天堂小草播放| 九九免费精品视频在这里| 亚洲熟妇AV一区二区三区浪潮 | 毛片在线免费视频| 成年女人午夜毛片免费视频| 少妇人妻偷人精品免费视频| 一边摸一边爽一边叫床免费视频| 国产成人高清亚洲一区久久|