上次在我的博客中讲述了quest公司的spotlight系列软件,这次来扯淡一下quest公司的另一测试辅助软件 datafactory(数据工厂),顾名思义,数据工厂是生产数据的,主要应用领域是性能测试中的大数据量测试, 也就是性能测试数据准备阶段。
原理说明:
通过和数据库进行连接后,对选定表的字段设定一定的插入规则,然后批量插入记录。Datafactory支持各种主流数据库(oracle、DB2、MS SQL),甚至excel、access等。下面以以主流的oracle为例进行说明。
环境说明:
Oracle10g,创建2个表,一个是testtable,一个testtable2。计划用datafactory往testtable中插入记录,其中需要读取testtable2中的部分字段信息。testtable表的字段类型如下(字段类型已经尽可能覆盖多种情况):
Testtable表:
Testable2字段类型和testtable类似,里面记录情况如下:
编号 | 姓名 | 性别 | 出生日期 | 毕业院校 | 分数 | 照片 | 考核情况 |
1 | 张三 | 1 | 2009-12-21 | 北京大学 | 85.5 | <BLOB> | <NCLOB> |
2 | 李四 | 0 | 2002-7-16 | 清华大学 | 78.2 | <BLOB> | <NCLOB> |
3 | 王五 | 1 | 1999-6-8 | 湖南大学 | 65.5 | <BLOB> | <NCLOB> |
详细操作描述:
安装完datafactory之后,进入file菜单下面点击new,然后选择oracle数据库类型。
然后会要求输入oracle的net服务,和连接的用户名和密码。
选择要插入记录的表。
进入设置插入表规则界面,对每个字段的插入规则在右边界面进行设置。
设定规则,testtable表中编号字段为long integer类型,这里设定为插入顺序值(insert sequential values)。
设定规则,testtable表中姓名字段为vachar2类型,这里设定从testtable2表中查询结果随机取值。
设定规则,testtable表中出生日期为date类型,这里设定设定一个随机的时间,时间跨度为1982年-1988年的任何一天。
设定规则,testtable表中分数为为number类型,这里设定设定一个随机数值,数字跨度为50-85.5。
设定规则,testtable表中考核情况为NCLOB类型,这里设定随机从文件夹中的text文件获得内容。
设定规则,testtable表中照片为BLOB类型,这里设定随机从文件夹中的获得图片。
设定完毕后,点击上面的run按钮,成功执行插入。插入后的效果如下所示:
引发的另外一个问题:
因为datafactory试用版只能每次插入100条数据,购买正版又没有钱,而大数据量的测试动不动就要100万级的数据,那要准备100万条数据可是要点10000次鼠标啊,那样的话,性能测试还没有开始,人就已经崩溃了。其实,有很多办法能够解决这个问题。如写一个多线程的程序,反复触发插入事件。当然最简单的办法,还是用HP公司的Loadrunner录一段插入的脚本,然后设定几个虚拟用户(原理上也是多线程插入的方式)进行插入就可以轻松搞定了。
录制插入脚本,把整个插入操作当作一个事务。
设定场景,这里设定8个虚拟用户,并发插入,时限为5分钟。
场景运行情况,插入事务一共通过了2635个。
从上面的事务来看,一共有2635个事务通过,因为试用版每次插入100条数据,则应该插入的总记录数为:2635×100=263500条,进入数据库,执行查询,可以发现记录数正确。
- INSERT INTO `status` VALUES ('0', 'available');
- INSERT INTO `status` VALUES ('1', 'offline');
- INSERT INTO `status` VALUES ('2', 'unknown');
- INSERT INTO `status` VALUES ('3', 'unavilable');
- SET FOREIGN_KEY_CHECKS=0;
- -- ----------------------------
- -- Table structure for pool
- -- ----------------------------
- CREATE TABLE `pool` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) NOT NULL,
- `wideip_id` int(11) NOT NULL,
- `enable` tinyint(4) NOT NULL,
- `status_id` tinyint(4) NOT NULL,
- PRIMARY KEY (`id`),
- KEY `wideip_pool_fk` (`wideip_id`),
- KEY `status_pool_fk` (`status_id`),
- CONSTRAINT `status_pool_fk` FOREIGN KEY (`status_id`) REFERENCES `status` (`id`),
- CONSTRAINT `wideip_pool_fk` FOREIGN KEY (`wideip_id`) REFERENCES `wideip` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
- ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
-
- -- ----------------------------
- -- Table structure for status
- -- ----------------------------
- CREATE TABLE `status` (
- `id` tinyint(4) NOT NULL,
- `name` varchar(255) NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-
- -- ----------------------------
- -- Table structure for wideip
- -- ----------------------------
- CREATE TABLE `wideip` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) NOT NULL,
- `enable` tinyint(4) NOT NULL,
- `status_id` tinyint(4) NOT NULL,
- PRIMARY KEY (`id`),
- KEY `status_id` (`status_id`),
- CONSTRAINT `wideip_ibfk_1` FOREIGN KEY (`status_id`) REFERENCES `status` (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
- INSERT INTO `status` VALUES ('0', 'available');
- INSERT INTO `status` VALUES ('1', 'offline');
- INSERT INTO `status` VALUES ('2', 'unknown');
- INSERT INTO `status` VALUES ('3', 'unavilable');
- /*清空所有数据数据*/
- drop procedure if exists clear_all_data;
- delimiter ;;
- create procedure clear_all_data()
- BEGIN
- /*清空数据*/
- delete from wideip;
- /*让自增从1*/
- alter table wideip auto_increment 1;
- /*清空pool数据*/
- delete from pool;
- /*让pool自增从1*/
- alter table pool auto_increment 1;
- END;;
- delimiter ;
-
-
- drop procedure if exists make_pool_data;
- /*造每个wideip对于的pool数据*/
- delimiter ;;
- create procedure make_pool_data(wideipId int)
- BEGIN
- declare d_enable int default 0;
- declare d_status_id int default 0;
- declare isError int default 0;
- declare Done int default 0;
- declare i int default 0;
-
- /* 声明游标 */
- DECLARE rs CURSOR FOR select id from status order by id;
-
- /* 异常处理 */
- DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done = 1;
- DECLARE CONTINUE HANDLER FOR 1146 SET isError=1;
-
- REPEAT
- /* 打开游标 */
- OPEN rs;
- REPEAT
- /*取status_id*/
- FETCH rs INTO d_status_id;
- IF Done!=1 THEN
- select d_enable,d_status_id;
- set i=i+1;
- insert into pool(name,enable,status_id,wideip_id) values(concat("name",wideipId,"_",i),d_enable,d_status_id,wideipId);
- END IF;
- UNTIL d_status_id is NULL or Done=1 END REPEAT;
- CLOSE rs;
- set d_enable=d_enable+1;
- set Done=0;
- UNTIL d_enable >= 2 END REPEAT;
- END;;
- delimiter ;
-
-
- drop procedure if exists make_wideip_data;
- /*造wideip的数据并调用 make_pool_data */
- delimiter ;;
- create procedure make_wideip_data()
- BEGIN
- declare d_enable int default 0;
- declare d_status_id int default 0;
- declare isError int default 0;
- declare Done int default 0;
- declare i int default 0;
- declare newWideipId int default 0;
-
- /* 声明游标 */
- DECLARE rs CURSOR FOR select id from status order by id;
-
- /* 异常处理 */
- DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done = 1;
- DECLARE CONTINUE HANDLER FOR 1146 SET isError=1;
-
- REPEAT
- /* 打开游标 */
- OPEN rs;
- REPEAT
- /*取status_id*/
- FETCH rs INTO d_status_id;
- IF Done!=1 THEN
- select d_enable,d_status_id;
- set i=i+1;
- insert into wideip(name,enable,status_id) values(concat("name",i),d_enable,d_status_id);
- set newWideipId=last_insert_id();
- call make_pool_data(newWideipId);
- END IF;
- UNTIL d_status_id is NULL or Done=1 END REPEAT;
- CLOSE rs;
- set d_enable=d_enable+1;
- set Done=0;
- UNTIL d_enable >= 2 END REPEAT;
- END;;
- delimiter ;