【问题标题】:Integration testing on live test website, restoring the data after test suite completion在现场测试网站上进行集成测试,测试套件完成后恢复数据
【发布时间】:2015-07-09 18:14:46
【问题描述】:

我想使用实时网站的 selenium 编写集成/自动化测试用例,例如 testing.example.com。该站点是example.com的暂存站点。

当我运行测试用例时,会创建、更新、删除新数据。完成测试套件后,我想将数据库恢复到运行测试用例之前的状态。

因此,例如运行测试用例之前的数据库状态 --> s1 以及运行测试用例后的数据库状态 --> s2

我希望数据库回到 s1 状态。

我正在使用 rails 框架和 mysql/pg 数据库

一种解决方案可能是在运行测试用例之前转储数据库,然后在测试用例运行完成后恢复数据。

还有什么其他的解决方案?

谢谢

【问题讨论】:

  • 我认为这是您提到的唯一解决方案。进行数据库备份,然后在测试完成后将其还原。或者您可以设置虚拟数据库并在运行测试时对其进行配置,并在测试完成后配置实际数据库。
  • 它会在索引中产生问题吗??
  • 我认为它不会对现有索引造成任何问题。

标签: mysql ruby-on-rails postgresql selenium integration-testing


【解决方案1】:

在数据库变大并且程序变长之前,我完全采用了该解决方案。

所以我把它改成了一种回滚。

作为设置的一部分 所有测试用例调用的主类

  def run_once_beginning
    DEBUG("start","Running start function")
    DefaultDatabase.prepare_rollback
    DefaultDatabase.resetDB
  end

  def run_once_end
    DEBUG("start","Running end function")
    DefaultDatabase.drop_all_triggers
    DefaultDatabase.resetDB
  end

  def setup    
    if(State.instance.started == false)
      State.instance.started = true
      run_once_beginning
      at_exit do
        run_once_end
      end
    end
  end

DefaultDatabase.rb

def prepare_rollback

   query = "CREATE TABLE IF NOT EXISTS `changes` (`table_name` varchar(60) NOT NULL, PRIMARY KEY (`table_name`))"
HandleDB.sendQuery(query)

   query = "show tables;"
   tables = HandleDB.sendQuery(query)
   exclude = ["phpsessions", "cameras", "changes", "connections", "sysevents"]
   triggers = "";
   tables.each{ |name|
     if (exclude.index(name) == nil)
       triggers += "DROP TRIGGER IF EXISTS ins_#{name};"
       triggers += "CREATE TRIGGER ins_#{name} AFTER INSERT ON #{name}
                 FOR EACH ROW BEGIN
                 INSERT IGNORE INTO `changes` VALUES ('#{name}');
                 END;"
       triggers += "DROP TRIGGER IF EXISTS up_#{name};"
       triggers += "CREATE TRIGGER up_#{name} AFTER UPDATE ON #{name}
                 FOR EACH ROW BEGIN
                 INSERT IGNORE INTO `changes` VALUES ('#{name}');
                 END;"
       triggers += "DROP TRIGGER IF EXISTS del_#{name};"
       triggers += "CREATE TRIGGER del_#{name} AFTER DELETE ON #{name}
                 FOR EACH ROW BEGIN
                 INSERT IGNORE INTO `changes` VALUES ('#{name}');
                 END;"
     end
   }

   setup_connecion = Mysql.new(Constants::DB["ServerAddress"],"root", Constants::DB["Password"],
  Constants::DB["Database"],Constants::DB["ServerPort"], nil, Mysql::CLIENT_MULTI_STATEMENTS)

   setup_connecion.query(triggers)

# Clear out all the results.
   while setup_connecion.more_results
     setup_connecion.next_result
   end
   query = "DROP PROCEDURE IF EXISTS RestoreProc;"
   setup_connecion.query(query)

# This is a mysql stored procedure. It will use a cursor for extracting names of
# changed tables from the changed-table and then truncate these tables and
# repopulate them with data from the default db.
   query = "CREATE PROCEDURE RestoreProc()
     BEGIN
       DECLARE changed_name VARCHAR(60);
       DECLARE no_more_changes INT DEFAULT 0;
       DECLARE tables_cursor CURSOR FOR SELECT table_name FROM changes;
       DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_changes = 1;

       OPEN tables_cursor;
       FETCH tables_cursor INTO changed_name;

       IF changed_name IS NOT NULL THEN
         REPEAT
           SET @sql_text=CONCAT('TRUNCATE ', changed_name);
           PREPARE stmt FROM @sql_text;
           EXECUTE stmt;
           DEALLOCATE PREPARE stmt;

           SET @sql_text=CONCAT('INSERT INTO ', changed_name, ' SELECT * FROM default_db.', changed_name);
           PREPARE stmt FROM @sql_text;
           EXECUTE stmt;
           DEALLOCATE PREPARE stmt;

           FETCH tables_cursor INTO changed_name;
         UNTIL no_more_changes = 1
         END REPEAT;
       END IF;

       CLOSE tables_cursor;
       TRUNCATE changes;
   END ;"

   setup_connecion.query(query)
   setup_connecion.close
end

def drop_all_triggers
    query = "show tables;"
    tables = HandleDB.sendQuery(query)
    triggers = ""
    tables.each{ |name|
      triggers += "DROP TRIGGER IF EXISTS del_#{name};"
      triggers += "DROP TRIGGER IF EXISTS up_#{name};"
      triggers += "DROP TRIGGER IF EXISTS ins_#{name};"
    }

    triggers_connection = Mysql.new(Constants::DB["ServerAddress"],"root", Constants::DB["Password"],
                     Constants::DB["Database"],Constants::DB["ServerPort"], nil, Mysql::CLIENT_MULTI_STATEMENTS)

    triggers_connection.query(triggers)
    triggers_connection.close
  end

def resetDB
    restore_connection = Mysql.new(Constants::DB["ServerAddress"],Constants::DB["User"], Constants::DB["Password"],
      Constants::DB["Database"], Constants::DB["ServerPort"], nil, Mysql::CLIENT_MULTI_RESULTS)
    restore_connection.query("CALL RestoreProc();")
    restore_connection.close
  end

为此需要原始数据库的副本,您希望它返回到名为“default_db”的状态。

“排除”是不会更改的表

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多