自动化 MySQL 的 Cucumber 测试场景

发布于 2024-10-20 08:15:13 字数 5104 浏览 1 评论 0原文

我建立了一个重要的MySQL数据库,有很多视图、触发器、函数和过程。

测试非常困难,并且不要忘记任何事情,因此,我为数据库的所有功能(插入、选择等、对函数和过程等的请求以及视图)编写了 Cucumber 场景,

这对我们有帮助当我们测试所有这些行为时,甚至在编写视图和其他代码之前,确定我们真正想做的事情非常有帮助。

我的问题是:编写完 Cucumber 功能后,我们都在 MySQL Shell 中手动测试。

我是 BDD/TDD 和敏捷方法的新手,但我做了一些搜索以了解如何进行一些自动化,但没有发现对我的案例非常有趣的内容。

有没有人可以提供一些有趣的方法来为此创建自动化?

我不了解 Ruby,但通过示例,是否可以直接将 RSPec 与 MySQL 一起使用(带有一些示例)?

或者用另一种语言,或者任何你能想到的解决方案!

提前致谢!

[编辑]


如果发现RSpec和MySQL的一些有趣的东西:

Mysql 对 Cucumber Nagios 的支持

mysql_steps.rb


我的问题是:我对 Ruby、RSPec 等没有任何知识。

我正在研究这本优秀的“Pick Axe”书,并且来自 PragProg 的 RSPec 书

但我将非常感谢给出以下代码的 RSpec 步骤的小示例:


MySQL 过程

DELIMITER $$

CREATE PROCEDURE `prc_liste_motif` (
    IN texte TEXT,
    IN motif VARCHAR(255),
    OUT nb_motif INT(9),
    OUT positions TEXT)
BEGIN
    DECLARE ER_SYNTAXE CONDITION FOR SQLSTATE '45000';
    DECLARE sousChaine TEXT;
    DECLARE positionActuelle INT(9) DEFAULT 1;
    DECLARE i INT(9) DEFAULT 1;

    IF
        LENGTH(motif) > LENGTH(texte)
    THEN
        SIGNAL ER_SYNTAXE
            SET MESSAGE_TEXT =
              'Bad Request: Le motif est plus long que le texte.',
              MYSQL_ERRNO = 400;
    END IF;

    SET positions = '';
    SET nb_motif = 0;

    REPEAT

        SET sousChaine = SUBSTRING_INDEX(texte, motif, i);

        SET positionActuelle = LENGTH(sousChaine) + 1;

        IF
          positionActuelle < LENGTH(texte) + 1
        THEN

            IF
              LENGTH(positions) > 0
            THEN
                SET positions = CONCAT(positions, ',');
            END IF;

            SET positions = CONCAT(positions, positionActuelle);

            SET nb_motif = nb_motif + 1;

        END IF;

        SET i = i + 1;

    UNTIL LENGTH(sousChaine) >= LENGTH(texte)
    END REPEAT;

END$$

Cucumber 功能:

Feature: Procedure prc_liste_motif
  In order to precess a string according to a given unit
  I want to know the number of units present in the chain and their positions
  Knowing that the index starts at 1

  Background: the database mydatabase in our SGBDR server
    Given I have a MySQL server on 192.168.0.200
    And I use the username root
    And I use the password xfe356
    And I use the database mydatabase

  Scenario Outline: Using the procedure with good values in parameters
    Given I have a procedure prc_liste_motif
    And I have entered <texte> for the first parameter
    And I have entered <motif> for the second parameter
    And I have entered <nb_motif> for the third parameter
    And I have entered <positions> for the fourth parameter
    When I call prc_liste_motif
    Then I should have <out_nb_motif> instead of <nb_motif>
    Then I should have <out_positions> instead of <positions>

    Exemples:
      | texte         | motif | nb_motif | positions | out_nb_motif | out_positions |
      | Le beau chien | e     |          |           | 3            | 2,5,12        |
      | Allo          | ll    |          |           | 1            | 2             |
      | Allo          | w     |          |           | 0            |               |

在 MySQL 中手动通过测试的示例:

$ mysql -h 192.168.0.200 -u root -p xfe356
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.9 MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> USE mydatabase
Database changed
mysql> SET @texte = 'Le beau chien';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @motif = 'e';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @nb_motif = NULL;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @positions = NULL;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @out_nb_motif = 3;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @out_positions = '2,5,12';
Query OK, 0 rows affected (0.00 sec)

mysql> CALL prc_liste_motif(@texte, @motif, @nb_motif, @positions);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @nb_motif = @out_nb_motif AND @positions = @out_positions;
+-----------------------------------------------------------+
| @nb_motif = @out_nb_motif AND @positions = @out_positions |
+-----------------------------------------------------------+
|                                                         1 |
+-----------------------------------------------------------+
1 row in set (0.00 sec)

提前感谢您的帮助!

I've built an important MySQL database, with a lot of view, triggers, functions and procedures.

It's very hard to test, and to not forget anything, so, I've written Cucumber scenarios for all of the features of my DB (Insert, Select, etc., request on functions an procedures etc., and views)

This help us a lot when we test the behavior of all this, and even before writing view and other code, it's very helpful to determinate want we really want to do.

My problem is: after writing Cucumber features, we all test by hand in a MySQL Shell.

I'm new in BDD/TDD and Agile methods, but I've done some search to know how to make some automation, but found nothing very interesting for my case.

Is there somebody who can provide some interesting way to create automation for this?

I don't know Ruby, but by example, is it possible to use RSPec directly with MySQL (with some examples)?

Or in another language, or any solution you can think of!

Thanks in advance!

[EDIT]


If found some interesting things with RSpec and MySQL:

Mysql Support For Cucumber Nagios

mysql_steps.rb


My problem is: I don't have any knoledge with Ruby, RSPec, etc.

I'm working on it with the excellent "Pick Axe" book, and RSPec book from PragProg

But I will be very grateful for a little example of of RSpec steps given the code below:


The MySQL Procedure

DELIMITER $

CREATE PROCEDURE `prc_liste_motif` (
    IN texte TEXT,
    IN motif VARCHAR(255),
    OUT nb_motif INT(9),
    OUT positions TEXT)
BEGIN
    DECLARE ER_SYNTAXE CONDITION FOR SQLSTATE '45000';
    DECLARE sousChaine TEXT;
    DECLARE positionActuelle INT(9) DEFAULT 1;
    DECLARE i INT(9) DEFAULT 1;

    IF
        LENGTH(motif) > LENGTH(texte)
    THEN
        SIGNAL ER_SYNTAXE
            SET MESSAGE_TEXT =
              'Bad Request: Le motif est plus long que le texte.',
              MYSQL_ERRNO = 400;
    END IF;

    SET positions = '';
    SET nb_motif = 0;

    REPEAT

        SET sousChaine = SUBSTRING_INDEX(texte, motif, i);

        SET positionActuelle = LENGTH(sousChaine) + 1;

        IF
          positionActuelle < LENGTH(texte) + 1
        THEN

            IF
              LENGTH(positions) > 0
            THEN
                SET positions = CONCAT(positions, ',');
            END IF;

            SET positions = CONCAT(positions, positionActuelle);

            SET nb_motif = nb_motif + 1;

        END IF;

        SET i = i + 1;

    UNTIL LENGTH(sousChaine) >= LENGTH(texte)
    END REPEAT;

END$

The Cucumber feature:

Feature: Procedure prc_liste_motif
  In order to precess a string according to a given unit
  I want to know the number of units present in the chain and their positions
  Knowing that the index starts at 1

  Background: the database mydatabase in our SGBDR server
    Given I have a MySQL server on 192.168.0.200
    And I use the username root
    And I use the password xfe356
    And I use the database mydatabase

  Scenario Outline: Using the procedure with good values in parameters
    Given I have a procedure prc_liste_motif
    And I have entered <texte> for the first parameter
    And I have entered <motif> for the second parameter
    And I have entered <nb_motif> for the third parameter
    And I have entered <positions> for the fourth parameter
    When I call prc_liste_motif
    Then I should have <out_nb_motif> instead of <nb_motif>
    Then I should have <out_positions> instead of <positions>

    Exemples:
      | texte         | motif | nb_motif | positions | out_nb_motif | out_positions |
      | Le beau chien | e     |          |           | 3            | 2,5,12        |
      | Allo          | ll    |          |           | 1            | 2             |
      | Allo          | w     |          |           | 0            |               |

An exemple of passed test by hand in MySQL:

$ mysql -h 192.168.0.200 -u root -p xfe356
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.9 MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> USE mydatabase
Database changed
mysql> SET @texte = 'Le beau chien';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @motif = 'e';
Query OK, 0 rows affected (0.00 sec)

mysql> SET @nb_motif = NULL;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @positions = NULL;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @out_nb_motif = 3;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @out_positions = '2,5,12';
Query OK, 0 rows affected (0.00 sec)

mysql> CALL prc_liste_motif(@texte, @motif, @nb_motif, @positions);
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @nb_motif = @out_nb_motif AND @positions = @out_positions;
+-----------------------------------------------------------+
| @nb_motif = @out_nb_motif AND @positions = @out_positions |
+-----------------------------------------------------------+
|                                                         1 |
+-----------------------------------------------------------+
1 row in set (0.00 sec)

thanks in advance for your help !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吃素的狼 2024-10-27 08:15:13

下面是一些伪代码,用于使用 RSpec 测试数据库的一种方法:

describe "prc_liste_motif" do
  before(:all) do
    # Set up database connection here
  end

  describe "good values" do
    context "Le beau chien" do
      let(:texte) { "Le beau chien" }
      # Set up other variables here
      let(:results) { # call prc_liste_motif here }

      it "has the correct out_nb_motif" do
        out_nb_motif = # however you derive this from the results of the procedure
        out_nb_motif.should == 3
      end

      it "has the correct out_positions" do
        # test out_positions here
      end
    end
  end
end

我在示例手动测试中注意到的一件事是如何检查结果:

 SELECT @nb_motif = @out_nb_motif AND @positions = @out_positions;

这将告诉您这两个值是否正确,但如果您得到 0对于此查询的结果,您不会立即知道这两个值中哪一个不正确,也不知道您得到的值是什么;获取该信息需要进行更多调查。

通过将这两个值的检查分成 2 个 RSpec 测试,当测试运行完成后,您可以知道两个值是否正确、一个是否不正确,或者两者是否都不正确。如果一个或两个都不正确,RSpec 还将返回一条失败测试的消息,显示“预期 3,得到 4”,这可以帮助您更快地进行调试。

当您为不同的输入添加更多测试时,我建议重构我在此处给出的伪代码以使用shared_examples_for。您已经阅读的 PragProg RSpec 书是一本很好的参考书。

Here is some pseudocode for one way you could test your database with RSpec:

describe "prc_liste_motif" do
  before(:all) do
    # Set up database connection here
  end

  describe "good values" do
    context "Le beau chien" do
      let(:texte) { "Le beau chien" }
      # Set up other variables here
      let(:results) { # call prc_liste_motif here }

      it "has the correct out_nb_motif" do
        out_nb_motif = # however you derive this from the results of the procedure
        out_nb_motif.should == 3
      end

      it "has the correct out_positions" do
        # test out_positions here
      end
    end
  end
end

One thing I noticed in your sample manual test was how you are checking the results:

 SELECT @nb_motif = @out_nb_motif AND @positions = @out_positions;

This will tell you whether or not those two values are correct, but if you get 0 results for this query, you do not immediately know which of the two values is incorrect and you do not know what the value you are getting instead is; getting that information requires more investigation.

By splitting up the checking for these two values into 2 RSpec tests, when the tests have finished running you can know if both are correct, if one is incorrect, or if both are incorrect. If one or both are incorrect, RSpec will also return a message for the failed test that says "Expected 3, got 4" which can help you debug faster.

As you add more tests for different inputs, I recommend refactoring the pseudocode I've given here to use shared_examples_for. The PragProg RSpec book that you're already reading is a great reference.

旧人 2024-10-27 08:15:13

Cucumber 是一种自然语言 BDD 工具,旨在让非技术利益相关者参与进来,以便您可以与他们讨论系统应该做什么。它还可以让您轻松地重复使用步骤 - 类似的上下文、事件和结果。

如果您正在编写数据库,我认为您的用户以及该数据库的受众很可能是技术人员。重用步骤的机会也可能有限,因此 Cucumber 可能不是最好的工具。您关于转向 RSpec 之类的东西可能是正确的。英语工具引入了一个抽象层和维护的另一个方面,这可能会让人头疼,所以我会选择一个适合你正在做的事情的工具,而不是从工具开始并试图适应你的需求。围绕它的需求。

完成此操作后,您可以使用 ActiveRecord 从查询中创建域对象结果,也可以直接调用 SQL。 RSpec 只是带有一些匹配器的 Ruby。 此论坛可能会对您有所帮助。

您还可以做的其他事情是构建一个实际使用您的数据库的小应用程序。这不仅可以确保您的数据库具有真正的价值;它将为用户提供如何使用它的示例。使用 Rails 做到这一点并不困难。如果您沿着这条路线走下去,那么您可以将 Cucumber 与 Webrat 或 Watir 之类的东西一起使用(如果您愿意的话),因为您将记录其他应用程序可以使用您的数据库进行的操作更高的水平。只要确保

  1. 您提供的任何实例都转到
    测试数据而不是生产数据,以及

  2. 你的小示例应用程序
    突然变成真正的应用程序
    (有时会发生),您可以发现这种情况并采取适当的政治和财务措施。

Java 对 MySQL 也有相当多的支持,你可以使用 Hibernate 代替 ActiveRecord,但我认为 Ruby 的维护成本会低。

Cucumber's a natural-language BDD tool, which is designed to get non-technical stakeholders on board so that you can have conversations with them about what the system should do. It also lets you reuse steps quite easily - similar contexts, events and outcomes.

If you're writing a database, I think it's likely that your users, and the audience for that database, will be technical. There may also be limited opportunities for reusing steps, so Cucumber may not be the best tool. You're probably right about moving to something like RSpec instead. The English-language tools introduce a layer of abstraction and another aspect to maintenance which can be a pain in the neck, so I'd pick a tool which suits what you're doing, rather than starting with the tool and trying to fit your needs around it.

Once you've done that, you can either use ActiveRecord to create domain-object results from your queries, or you can just call the SQL directly. RSpec is just Ruby with some matchers. This forum might help you.

Something else you could do is to knock up a small application which actually uses your database. Not only will this ensure that your database is genuinely valuable; it will provide users with examples of how to use it. That won't be very difficult to do with Rails. If you go down this route, then you can use Cucumber with something like Webrat or Watir if you want to, because you'll be documenting the kind of things that other applications could use your database for at a higher level. Just make sure that

  1. any live examples you provide go to
    test data instead of production, and
    that

  2. if your little example app
    suddenly turns into the real app
    (which sometimes happens), you're in a position to spot that happening and take appropriate political and financial steps.

Java also has quite a lot of support for MySQL and you could use Hibernate instead of ActiveRecord, but I think the maintenance costs will be much less in Ruby.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文