# Concordia Language

## Line comments

### Common line comment

It makes the compiler to **ignore a piece of text**. Example:

```
# This is a comment

Feature: Pay with Credit Card  # This is also a comment
```

### Special line comment

{% hint style="info" %}

* Local declaration.
* At most one declaration per file.
* Take precedence over a CLI option or configuration file option.
  {% endhint %}

They are:

* `#language: <value>` defines the document's language, where `<value>` is an available language such as `en` (English) or `pt` (Portuguese).
* ~~`#locale: <value>` defines document's locale, where `<value>` is an available local such as `en-US` (USA English) or `pt-BR` (Brazilian Portuguese).~~ **NOT AVAILABLE YET.**

Example:

```
#language: pt

Funcionalidade: Pagar com Cartão de Crédito
```

## Tag

A tag adds metadata to a declaration.

{% hint style="info" %}

* Local declaration.
* Allowed more than one tag per language construction.
  {% endhint %}

A tag starts with `@`. Multiple tags can be declared in a single line. Examples:

```
...

@critical @slow
Feature: Print Coupon
  
  ...

  @gui
  Variant: Print to PDF
    ...
  
  @device
  Variant: Print to Plotter
    
```

Some tags can receive parameters. Examples:

```
@importance( 6 )
Feature: Register Employee
  ...
  

@extends( Date )
UI Element: Birth Date
  ...
```

### Special tag

A special tag **changes the compiler's behavior**. These are special tags:

* **`@scenario( <number> )`**: references a [Scenario](#scenario) by its index, starting at 1.
* **`@variant( <number> )`**: references a [Variant](#variant) by its index, starting at 1.
* **`@importance( <number> )`**: indicates the importance of a declaration. The importance is as high as its number.
* **`@generated`**: indicates that a [Test Case](#test-case) was computer-generated.
* **`@fail`**: indicates that a [Test Case](#test-case) should fail.
* **`@ignore`**: whether applied to a [Variant](#variant), the Variant will not produce Test Cases; whether applied to a [Test Case](#test-case) it will not produce test scripts.
* **`@generate-only-valid-values`**: avoids that a [UI Element](#ui-element)'s property be used for generating values considered invalid. This is specially useful for using with masked input fields, in which the system does not let a user to type invalid characters on it. For instance:

  ```
    UI Element: Year
      - data type is integer
      @generate-only-valid-values
      - format is "/^[0-9]{1-3}$/"
      Otherwise I must see "Year must be a number."
  ```

  The above example will avoid generating invalid input values (*e.g.,* "A") for testing the format of the Year.

Reserved for future use:

* **`@global`** makes a UI Element globally accessible. Global UI Elements must not have the same name. Local UI Elements (the default) overrides global UI Elements.
* **`@extends( <name> )`**

### Common tag

A common tag is **ignored by the compiler** and aims to provide meaningful metadata for a declaration. Any tag that is not a special tag is considered a common tag. Examples:

* `@critical` may indicate that the current feature is critical for the project;
* `@issue(20)` may indicate that a feature (or scenario or variant) is being implemented in the Issue 20 from the Issue control system.

## Feature

> Desired behavior of a software system

{% hint style="info" %}

* Global declaration with unique name, at most one declaration per file.
* Sentences are **optional** and are not used for generating test cases.
* **Business-oriented** sentences, written as a [User Story](https://en.wikipedia.org/wiki/User_story).
  {% endhint %}

A Feature can be a piece of functionality or some needed, wished or distinguish characteristic of a system.

Example:

```
Feature: Administrator Login
```

Feature sentences should try to describe the contribution that the Feature brings to the **business** addressed by the software system. They are optional, but recommended. Example:

```
Feature: Login
  As a registered user
  I would like to access to the system using my credentials
  So that the system prevents unauthorized access
```

> In the above example the benefit to the business is to prevent unauthorized access.

Concordia adopts a wide-spread template for describing them: [User Story](https://en.wikipedia.org/wiki/User_story). A User Story template goes like this:

```
As a <role>
I would like to <capability>
So that <benefit>
```

The order of the sentences can vary. A `<role>` is usually a type of user or stakeholder. A `<capability>` is what the role wants to perform in order to achieve the `<benefit>`, which often is the contribution to the business.

## State

> A certain state of the system

{% hint style="info" %}

* Local declaration, only accepted inside[`Variant`](https://concordialang.gitbook.io/concordialang/language/broken-reference)sentences.
* Used for generating test cases.
  {% endhint %}

A State is denoted by a text between tilde (`~`), such as `~a state~`, and must be written inside [Variant](#variant) sentences. Example:

```
Then I have a ~user logged in~
```

A [Variant](#variant) can both produce or require states. A State is **produced** by a `Then` sentence, like in the prior example. A State is **required** by a `Given` or a `When` sentence. For instance:

```
Given that I have ~user logged in~
```

By declaring a required State, you're establishing a **dependency** among the current [Variant](#variant) and the ones that can produce it. Since that State is often produced by a Variant from another Feature, you have to [import](#import) the corresponding Feature file. *Concordia Compiler will only search for states from imported Feature files.*

When transforming Variants into [Test Cases](#test-case), Concordia Compiler will:

* Remove any (`Then`) sentences with a **produced** State; and
* Replace any (`Given` or `When`) sentences with a **required** State by sentences from the Variant that can produce it.

Whether there are different [Variant](#variant)s that can produce a (same) **required** State, Concordia Compiler will be able to combine each of them with the current Variant, aiming to produce [Test Cases](#test-case) that explore different execution paths. For more information, please read the section [Test Coverage and Techniques](https://concordialang.gitbook.io/concordialang/how-it-works/techniques).

Let's say that we have a simple Login feature like this:

{% tabs %}
{% tab title="login.feature" %}

```
Feature: Login

Scenario: Sucessful login

  Variant: Login with username and password
    Given that I am on the [Login Screen]
    When I enter with "bob" in {Username}
      and I enter with "123456" in {Password}
      and I click on {OK}
    Then I see "Welcome"
      and I have ~user logged in~


Constants:
  - "Login Screen" is "/login"
  
UI Element: Username

UI Element: Password

UI Element: OK
  - type is button
```

{% endtab %}
{% endtabs %}

Now let's suppose that a user has to be logged in to access its account details:

{% tabs %}
{% tab title="my-account.feature" %}

```
import "login.feature"

Feature: My Account

  Scenario: See my account data
  
    Variant: Show basic data by default
      Given that I have ~user logged in~
        and I am on the [Account Screen]
      Then I see {User} with "bob"
        and I see {Name} with "Robert Downey Jr"


Constants:
  - "Account Screen" is "/account"
        
UI Element: User
```

{% endtab %}
{% endtabs %}

Concordia Compiler will produce `my-account.testcase` with a [Test Case](#test-case) like the following, that includes sentences from both the features:

```
import "my-account.feature"

@scenario(1)
@variant(1)
Test Case: See my account data - 1
  Given that I am on the "/login"
  When I enter with "bob" in <username>
    and I enter with "123456" in <password>
    and I click on <ok>
  Then I see "Welcome"
  Given that I am on the "/account
  Then I see <user> with "bob"
    and I see <name> with "Robert Downey Jr"
```

## Scenario

> High-level, business-focused, usage scenario of a Feature.

{% hint style="info" %}

* Local declaration with a unique name.
* One or more declarations per Feature.
* Sentences are **optional** and are not used for generating test cases.
* **Business-oriented** sentences that follow the template [Given-When-Then](https://www.agilealliance.org/glossary/gwt/).
  {% endhint %}

Example:

```
Feature: Sales Report

  Scenario: Daily sales report
    Given that I am authenticated as a manager
    When I open the sales report
      and I choose the option "Daily report"
    Then I see a list with all the today's sales 
      and the total value
```

Template:

```
Given <some context or precondition>
  and <other context or precondition>
  and <other context or precondition>
  ... 
When <some action is carried out>
  and <other action is carried out>
  and <other action is carried out>
  ...
Then <a result or postcondition is observed>
  and <another result or postcondition is observed>
  and <another result or postcondition is observed>
  ...
```

## Variant

> Test-oriented declaration that describes a possible interaction between a *user* and the *system* in order to accomplish a Scenario.

{% hint style="info" %}

* Local declaration, one or more per Scenario.
* Sentences are used for generating test cases.
* **Test-oriented** sentences that follow the template [Given-When-Then](https://www.agilealliance.org/glossary/gwt/) and **first-person singular** ("I").
  {% endhint %}

A Variant must use the **Given-When-Then template** (see [Scenario](#scenario)) and **first person singular** ("`I`") in its sentences. Concordia Compiler uses [Natural Language Processing (NLP)](https://en.wikipedia.org/wiki/Natural_language_processing) techniques to understand them.&#x20;

{% hint style="warning" %}
See the [Actions that you can write](https://concordialang.gitbook.io/concordialang/language/actions) in Variant sentences.
{% endhint %}

Example:

```
Feature: New User

Scenario: Successful registration

  Variant: Register with a new account
    Given that I am on the [New Account Screen]
    When  I fill {Name}
      and I fill {Date of Birth}
      and I enter with "bob@example.com" in <#email>
      and I inform 123 in <#pass>    
      and I type 123 in <#confirmation>
      and I click <#ok>
    Then I have a ~registered user~
      and I see "Welcome, Bob" 

...
```

Things that can be part of Variant sentences:

1. **References to** [**Constants**](#constants), such as `[New Account Screen]`&#x20;
2. **References to** [**UI Elements**](#ui-element), such as `{Name}` or  `{New User:Name}`.
3. [**Widgets**](#widgets), such as `<#ok>`
4. [**States**](#state), such `~registered user~`
5. **Values** such as `"bob@example.com"`
6. **Numbers** such as `123`

#### Best practices

* Make sure that your **preconditions** are part of the group with `Given` sentences.
* Make sure that your **actions** are part of the group with `When` sentences.
* Make sure that your **post-conditions** are part of the group with `Then` sentences.
* Whenever possible, use a single `Given` , a single `When` and a single `Then` sentence. Use`and` for the other sentences.
* Write a **single action** per sentence.
* Do not use `and`in the middle of a sentence (break it, instead).
* Use an additional indentation for `and` sentences.

### Widgets

Variant sentences can have widgets (of the user interface) denoted between `<` and `>`. Example:&#x20;

```
When I fill <#firstName> with "Alice"
```

Concordia adopts the well-known [CSS query selectors](https://www.w3schools.com/css/css_selectors.asp) to locate widgets. Plugins convert these selectors to the format adopted by the testing framework.

**Available locators**:

| Locator  | Purpose                                                                          | Example                                  |
| -------- | -------------------------------------------------------------------------------- | ---------------------------------------- |
| `#`      | To find a widget by its **id**.                                                  | `When I click on <#save>`                |
| `.`      | To find a widget by its **class**.                                               | `When I click on <.btn-primary>`         |
| `@`      | To find a widget by its **name**.                                                | `When I click on <@save>`                |
| `~`      | To find a widget by its **mobile name**.                                         | `When I click on <~save>`                |
| `//`     | To find a widget by its [XPath](https://www.w3schools.com/xml/xpath_syntax.asp). | `When I click on <//form/div/button[1]>` |
| *(none)* | To find a widget by its **type**.                                                | `When I click on <button>`               |

{% hint style="success" %}
Whether you are testing a web application, you may find [Katalon-Concordia](https://github.com/thiagodp/katalon-concordia) useful. It's a browser extension - available for Google Chrome and Mozilla Firefox - that extends Katalon Recorder to save a recorded interaction as  `Variant` sentences.  Using it may reduce the time needed to locate the widgets of an existing application.&#x20;
{% endhint %}

## Constants

> Declaration block with constant values

{% hint style="info" %}

* Global declaration (can be used by other files).
* At most one declaration per file.
* Constants cannot have the same name of a [Table](#table) or a [Database](#database).
  {% endhint %}

A **`Constants`** block can define one or more constants, preceded by a dash sign (`-`). Both constant names and values are declared between quotes, except for numeric values - that can be declared without quotes. Example:

```
Constants:
  - "Home" is "/home"
  - "App Name" is "Acme"
  - "Mininum Age" is 18
  - "Pi" is 3.1416
```

Constant values are accessible by their names between `[` and `]`. Examples for the constants above:

```
Variant: Example
  Given that I visit [Home]
    and I see [App Name]
  # ...
  
UI Element: Age
  - minimum value is [Minimum Age]
    Otherwise I see "Invalid age."
    
UI Element: Some Math Value
  - maximum value is [Pi]
```

## Table

> Defines a data table that can be used by UI Elements' properties.

{% hint style="info" %}

* Global declaration (can be used by other files).
* Zero, one or many declarations per file.
* Tables cannot have the same name of a [Constant](#constants) or a [Database](#database).
  {% endhint %}

A table must have a unique name. Their rows are denoted between pipe (`|` ). The first row must provide the column names. Other rows must provide the corresponding data. Example:

```
Table: professions
  | name      | min_salary |
  | Magician  | 100000.00  |
  | 
```

Table declarations are transformed into in-memory tables that can be queried by UI Element properties for selecting test data. Tables can be queried using SQL. Like [Constants](#constants), their names must be referenced between `[` and `]`. Example:

```
UI Element: Profession
  - value comes from "SELECT name FROM [professions]"

UI Element: Salary
  - minimum value comes from "SELECT min_salary from [professions] WHERE name = {Profession}"
```

## Database

> Declares a database connection that can be used for test data selection

{% hint style="info" %}

* Global declaration.
* Names are shared with Constants and Tables.
* Allowed more than one declaration per file.
* Property values must be declared between quotes (`"`).
  {% endhint %}

Example 1:

```
Database: My DB
  - type is "mysql"
  - host is "http://127.0.0.1"
  - name is "mydb"
  - username is "admin"
  - password is "p4sss"
```

Example 2:

```
Database: Another DB
  - type is "json"
  - path is "C:\path\to\db.json"
```

{% hint style="success" %}
Database support needs installation of the corresponding drives. See [Using Databases](https://concordialang.gitbook.io/concordialang/introduction/databases) for more information on how to install them.
{% endhint %}

Properties:

| Property   | Description                                                                                                                                                                                                                                                    | Required |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `type`     | Database type. Examples: `"adodb"`, `"csv"`, `"firebase"`, `"ini"`, `"json"`, `"mysql"`, `"mssql"`, `"postgres"`, `"sqlite"`, `"xlsx"`.  See [Using Databases](https://concordialang.gitbook.io/concordialang/introduction/databases) for all supported types. | Yes      |
| `host`     | URL that indicates where the database is hosted.                                                                                                                                                                                                               | Vary     |
| `port`     | Network communication port used to connect to the database. Whether not defined, the default database port will be used, according to the property `type`.                                                                                                     | No       |
| `name`     | Database name. Used when there is a database server (whose location is defined by the property `host`) and the database is accessible by its name.                                                                                                             | Vary     |
| `path`     | Database path. Used when the database is accessed through the file system, such as the types `csv`, `ini`, `json`, `sqlite` and `xlsx`.                                                                                                                        | Vary     |
| `username` | Username used to connect to the database. When not defined, the database's default user will be used, according to the property `type`.                                                                                                                        | No       |
| `password` | Password used to connect to the database. When not defined, the database's default password will be used, according to the property `type`.                                                                                                                    | No       |
| `options`  | Database-specific connection options.                                                                                                                                                                                                                          | No       |

## UI Element

## Import

> Imports declarations from a `.feature` file

{% hint style="info" %}

* Local declaration.
* Give access to the declarations from the imported file.
  {% endhint %}

Examples:

```
import "file1.feature"
import "path/to/file2.feature"
```

## Test Case

## Test Events
