RASA - Rules and testing forms
Tags: rasa, chatbot, nlp, ai
Published: 2021-03-18 10:28:17

In the [previous chapter](https://dev.to/petr7555/rasa-creating-forms-bg8) we have created a newsletter form and wrote a story for it. Although this worked, there is a better way of invoking form loop when **subscribe** intent is recognized.

But before we make any changes, let's write a test for our form to make sure that the changes we are about to make do not break anything.

## <a name="testing"></a> Testing form happy path
Let's add the following test story to our `tests/test_stories.yml` file.
```yml
# tests/test_stories.yml
# ... previous contents ...
  - story: newsletter form happy path
    steps:
      - user: |
          hi
        intent: greet
      - action: utter_greet
      - user: |
          I want to subscribe
        intent: subscribe
      - action: newsletter_form
      - active_loop: newsletter_form
      - user: |
          my email is [example@email.com](email)
        intent: inform_email
      - action: newsletter_form
      - user: |
          twice a week
        intent: inform_frequency
      - action: newsletter_form
      - active_loop: null
      - action: utter_subscribed
```
Let's go though this test line by line.
* First, we are saying, that when a user writes *"hi"*, it should be classified as **greet** intent, followed by **utter_greet** action.
* Then, when user writes *"I want to subscribe"*, it should be classified as **subscribe** intent, followed by **newsletter_form** action and **newsletter_form** should be activated.
* Then, user writes *"my email is example@email.com"*. This should be classified as **inform_email** intent and also **[example@email.com]()** should be classified as **email** entity from this message. 
* The **inform_email** should be followed by another **newsletter_form** action (asking for the frequency of emails).
* Then, when user writes *"twice a week"*, it should be classified as **inform_frequency** intent.
* At this point, all slots of the form are filled and we are saying that the form should end by `- action: newsletter_form` and `- active_loop: null`.
* Then, the chatbot should perform the **utter_subscribed** action, informing us about our subscription details.

Make sure our tests pass by running `rasa test`.
Now let's get back to our improvements!

## Rules
Rules describe parts of conversations that should always follow the same path no matter what has been said previously in the conversation.
We want our assistant to always respond to a certain intent with a specific action, so we use a rule to map that action to the intent.
In our case, we would like to trigger the **newsletter_form** whenever the user expresses the intent **subscribe**.
```yml
# data/rules.yml
version: "2.0"

rules:
  - rule: activate subscribe form
    steps:
      - intent: subscribe
      - action: newsletter_form
      - active_loop: newsletter_form
```
We also also want to trigger the **utter_subscribed** action once all the required information has been provided.
```yml
# data/rules.yml
# ... previous contents ...
  - rule: submit form
    condition:
      - active_loop: newsletter_form
    steps:
      - action: newsletter_form
      - active_loop: null
      - action: utter_subscribed
```
The **submit form** rule only applies when the **newsletter_form** is active to begin with. Once it is no longer active (`- active_loop: null`), the form is complete.

We now no longer need our **greet and subscribe** story and we can delete it from `data/stories.yml`.

By running `rasa test` you can see, that both our tests still pass!

Rules, however do not generalize to unseen conversations. You should reserve them for single-turn conversation snippets, and use stories to train on multi-turn conversations. More on this in the [documentation](https://rasa.com/docs/rasa/writing-stories#when-to-write-stories-vs-rules). 

You can learn more about rules in the [documentation](https://rasa.com/docs/rasa/rules).

In the next chapter, we will look at handling unhappy paths.

Repository for this tutorial:
{% github petr7555/rasa-dev-tutorial no-readme %}

You can checkout the state of the repository at the end of this tutorial by running:
```bash
git clone --branch 04-rules-and-testing-forms git@github.com:petr7555/rasa-dev-tutorial.git
```