星期四, 五月 04, 2017

基于springmvc的自动化测试系统构想

        做为一名多年的软件开发人员,软件质量一直是心口的一块石头,一直压抑着自己,因为软件质量的高低关乎我们每一个软件企业的生存和发展。

        事实证明软件的问题消灭在萌芽状态是成本最低的一种方式,因此在开发阶段需要进行大量的测试才能保证软件的质量。

        因此,我认为比较理想的开发模式为“测试驱动开发”,即在开发前首先设计测试用例,在测试用例的基础上进行开发。

       但是如此以来,项目的整体开发周期会加长,而且很多程序员从内心认为编写单元测试会增加自己的工作量,有编写单元测试的时间还不如编写代码能获得更高的效率,因此测试驱动开发往往达不到预期的效果。

      那么如何提高单元测试的效率呢?根据人类几千年的发展变迁史来看,提高效率的方式只有一种——使用工具。

    So,我们要想提高单元测试效率的方式就一种,制造一种自动化的单元测试工具,该工具应该可以进行下面的一些工作:

     1.  实现多项目的管理。一个测试驱动的平台应该可以管理多个项目。
     2.  实现项目基础开发框架的生成。根据项目的包名自动生成springmvc+mybatis+spring的开发框架。
    3. 测试用例管理。测试用例包含持久层测试用例、服务层测试用例、控制层测试用例。
    4. Mock系统的生成,对于无法测试的第三方系统可自动生成mock对象,最终能够基于mock对象完成测试。
    5. 集成测试管理。测试系统可配置复杂情况下的集成测试。
    6. 测试代码生成。系统可根据设置的测试用例自动生成单元测试代码并执行。
    7. 测试报告管理。测试完成后可通过界面阅读测试报告。
    8. 基于git的托管。系统可以将生成的项目发布到git中,以实现对系统版本的控制。
   10. 界面模板管理。系统可生成界面基础模板及模板使用说明文档,第三方前端可提交自己的模板,该模板可以与生成的系统进行整合。
   11. 数据模型定义。后期可定义数据模型,根据数据模型自动创建数据库,支持导入pdm文件。
   12. 系统文档生成。系统能够自动写文档模板,包括:用户手册、管理员手册、测试报告、api接口、数据字典。
   13. 系统可实现压力测试。系统可以使用jmeter实现压力测试报告。
    14. 系统菜单的定义。可定义系统菜单。
    15. 系统原型生成。
    16. 持续集成系统。
    17. 安全扫描。
  
   想象一下,有了这套工具,我们在后面进行项目开发时的场景吧:
   1. 搞清楚用户的需求。可使用系统用例图(user case)进行捕获。
   2. 创建一个项目,指定项目需要使用的数据库、系统包的规划。
   3. 创建数据模型,建立好数据模型(可导入pdm文件哦)
   4. 定义系统功能菜单。
   5. 生成系统基础框架。
   6. 定义单元测试用例。
   7. 程序员根据单元测试编写代码,实现业务逻辑。
   8. 编写集成测试用例。
   9. 生成jmeter压力测试文件并运行。
  10. 安全漏洞扫描。
 11. 生成系统文档。
   12. 交付,放心的交付吧,因为测试做了很多遍了,不会有问题的。


                  理想中的软件建模方法,谁有兴趣呢?留言联系我一起讨论讨论。
       

无题

想不好题目,暂时就叫无题吧。写点什么呢?说说自己想说的话吧。

想在夜深人静的晚上写点东西,内心很矛盾的,想让人看,又不想让人看,其实是想让不认识的人看,现在的网络已经很难隐藏一个人的身份了,大家在网上都像透明人一样,无处藏身。
纠结了半天,还是觉得blogger是我的心声。
第一,国内无法正常访问blogger,我的关系都在国内,大家基本上不会碰见。
第二,发表的东西国外人可能看见,或许能碰到欣赏的人吧。
第三,我还是喜欢使用google的产品。

纪念帖

        好久没有写过博客了,记得第一次使用blogger.com是在十年前,那时候的我还是意气风发的少年一个,如今孩子都已经三岁了,不知道谷歌的博客什么时候可以在国内继续被访问,但这对我来说已经不重要了,因为我自己能访问就可以了。
        后面的日子我不知道会写些什么,但还是供自己十年后再来评价吧。

星期五, 二月 26, 2010

星期四, 九月 13, 2007

innosetup对bde打包安装

一个朋友拿来一套软件,让我帮着做一个安装程序,这套软件是用Delphi开发的,其中用到了BDE,因此要求把BDE也一起打包安装。

我没用过BDE,更加不熟悉BDE的组成,刚开始不知道如何下手。由于我习惯使用InnoSetup来制作安装程序,便想到在InnoSetup的网站上也许有相关的介绍。于是登录InnoSetup的网站,在FAQ中找到了解决办法,现总结一下:

一、首先,在InnoSetup的网站上下载BdeInst.cab、MiniReg.exe、AddAlias.exe三个程序,其中BdeInst.cab就是BDE的安装包,其中只包含BdeInst.dll一个文件,有3兆多,将它提取出来。

二、将BdeInst.dll、MiniReg.exe、AddAlias.exe与要安装的应用程序放在一起。

三、在制作好的InnoSetup脚本中的相关节中加入以下内容:

[Files]
Source: "BdeInst.dll"; DestDir: "{tmp}"
Source: "MiniReg.exe"; DestDir: "{tmp}"
Source: "AddAlias.exe"; DestDir: "{tmp}"

[Run]
Filename: "{tmp}\MiniReg.exe"; Parameters: """{tmp}\BdeInst.dll"""
Filename: "{tmp}\AddAlias.exe"; Parameters: """Alias SubDir Driver"""

经过这样的改动,制作出来的Setup.exe就可以将应用程序连同BDE一块安装了。

之所以要用到MiniReg.exe和AddAlias.exe,是因为BdeInst.dll其实是一个COM组件,拷贝到用户机器上以后还需要注册一下才能用,MiniReg.exe就是做这个工作的,它的功能类似RegSvr32(不明白为什么不直接使用RegSvr32), MiniReg.exe是用Delphi编写的,源程序很短,顺便列在下面:

// FileName: MiniReg.dpr
program MiniReg;
{
  MiniReg v1.0 by Jordan Russell

  Note: For Delphi 3+, you'll need to change "OLE2" below to "ActiveX".
}
uses
  Windows, OLE2; // ActiveX

{x$R *.RES}

procedure RegisterServer(const Filename: String);
var
  LibHandle: THandle;
  RegisterServerProc: function: HRESULT; stdcall;
begin
  LibHandle := LoadLibrary(PChar(Filename));
  if LibHandle <> 0 then
  try
    @RegisterServerProc := GetProcAddress(LibHandle, 'DllRegisterServer');
    if Assigned(@RegisterServerProc) then
      RegisterServerProc;
  finally
    FreeLibrary(LibHandle);
  end;
end;

begin
  if ParamCount <> 1 then
    Exit;
  CoInitialize(nil);
  try
    RegisterServer(ParamStr(1));
  finally
    CoUninitialize;
  end;
end.

AddAlias的作用是向BDE注册一个别名,指向要连接的数据库(类似ODBC的数据源),它运行时需要三个命令行参数,分别是:别名、子目录名、驱动名。AddAlias也是用Delphi写的,源代码如下:

// FileName: AddAlias.dpr
program AddAlias;
{
  program adds a alias to the BDE configuration file

  parameters:
    0: programname + path (standard parameter of OS)
    1: Name of alias
       if begins with '-' then delete first if exist
                         else do nothing if exist
    2: path to data directory
    3: BDE driver name

  Bugfix: Savierhs Lopez Arteaga 3.1.2001
          AddAlias didn't delete alias with beginning '-'
}

uses
  Windows, SysUtils, BDE;

var
  GAlias:    string  = 'New';
  GDriver:   string = szPARADOX;
  GAliasDir: string;
  FParams:   string;
  FDrvName:  string;
  FDelete:   boolean;
  i:         integer;

function StrToOem(const AnsiStr: string): string;
begin
  SetLength(Result, Length(AnsiStr));
  if Length(Result) > 0 then
    CharToOem(PChar(AnsiStr), PChar(Result));
end;

begin
  for i := 1 to ParamCount do
  begin
    case i of
      1: GAlias    := ParamStr(1);
      2: GAliasDir := ParamStr(2);
      3: GDriver   := ParamStr(3);
    end;
  end;

  //default alias
  if GAliasDir = '' then GAliasDir := ExtractFilePath(ParamStr(0))+'Data';

  //should delete alias first? separate alias name
  if GAlias[1] = '-' then
  begin
    FDelete := True;
    //GAlias := Copy(GAlias, 1, Length(GAlias)); Bug
    Delete(GAlias, 1, 1);  //Fix by Savierhs Lopez Artega
  end else FDelete := False;

  FDrvName := GDriver;
  //set Parameters, the driver and server name
  if (CompareText(GDriver, szCFGDBSTANDARD) = 0) or
     (CompareText(GDriver, szPARADOX) = 0)       or
     (CompareText(GDriver, szDBASE) = 0)         or
     (CompareText(GDriver, szFOXPRO) = 0)        or
     (CompareText(GDriver, szASCII) = 0)         then
  begin
    if (CompareText(GDriver, szCFGDBSTANDARD) = 0) then FDrvName := szPARADOX;

    //set parameters for the new alias
    FParams := Format('%s:"%s"',  [szCFGDBPATH, GAliasDir]) +
               Format(';%s:"%s"', [szCFGDBDEFAULTDRIVER, GDriver]) +
               Format(';%s:"%s"', [szCFGDBENABLEBCD, szCFGFALSE]);
  end else begin
    if (CompareText(GDriver, 'INTRBASE') = 0)
    then FParams := Format('%s:"%s"',  [szSERVERNAME, GAliasDir])
    else FParams := Format('%s:"%s"',  [szDATABASENAME, GAliasDir]);

    //add other Parameters here !!!!!!!!!!!!!!!!!
  end;

  DbiInit(nil);
  try
    if FDelete then
      try
        DbiDeleteAlias(nil, PChar(GAlias));
      except
      end;

    try
      DbiAddAlias(nil, PChar(StrToOem(GAlias)),
                       PChar(StrToOem(FDrvName)),
                       PChar(FParams), True);
      DbiCfgSave(nil, nil, True);
    except
    end;

  finally
    DbiExit();
  end;

end.

杂感:

一、InnoSetup这个安装制作工具非常好用,它短小精致、公开源码、无需注册可免费使用,能满足绝大多数需要,我经常向人建议抛弃InstallShield这个庞然大物,使用InnoSetup。

二、原来的印象中,BDE也是个庞然大物,有10兆之巨,但这次的安装包只有3兆,很出乎意料。