Giter VIP home page Giter VIP logo

groq-test-suite's Introduction

GROQ test suite

The GROQ test suite is the official conformance test suite for the GROQ specification.

Status

The test suite (and the specification) was started in August 2019 and has good coverage of the basic features. Currently we're working on moving over tests from the internal GROQ implementation used in Sanity.

Versioning

The test suite uses the version scheme vX.Y.Z where X.Y follows the version of GROQ and Z is monotonically increasing.

Using the test suite

The YAML files in this repository is optimized for writing tests. For using the test suite it's recommended to use the compiled version. The compiled test suite is a NDJSON file where every entry uses the schema below.

The compiled test suite can either be downloaded from the GitHub Release page or be built from source (see next section).

type Entry = Dataset | Test

type Dataset = {
  _type: "dataset"
  _id: string

  name: string
  documents?: Array<any>
  url: string
}

type Test = {
  _type: "test"
  _id: string

  name: string
  filename: string
  query: string
  result: any
  valid: boolean
  dataset: {
    _type: "reference"
    _ref: string
  }
}

Compiling the test suite

Use the provided build script to compile the test suite:

# Install dependencies
$ yarn

# Build the test suite
$ yarn build # outputs to suite.ndjson
$ yarn build --stdout # outputs to stdout
$ yarn build --out=custom.ndjson # outputs to custom.ndjson
$ yarn build --pattern='**/misc.yml' # Only build for files which matched the pattern.
$ yarn build --baseDir=/some/dir' # Look for test  files in this base directory

Structure

The test suite is written in YAML files in the test/ directory. Here's an example file:

documents:
  - _id: "a"
    _type: "person"
    name: "George Michael Bluth"
  - _id: "b"
    _type: "company"
    name: "Bluth Inc."
    manager:
      _ref: "a"

tests:
  - name: "Resolve references"
    query: |
      *[_type == "company"][].manager->name
    result:
      - "George Michael Bluth"

Nesting tests

Tests can be nested and will then inherit properties from their parent.

Here's a slightly contrived example which shows how the dataset can be overridden for a specific test case:

# This test file:
documents:
  - _id: "a"
  - _id: "b"

tests:
  name: "Counting"
  query: |
    count(*)
  result: 2

  tests:
    - documents:
        - _id: "a"
        - _id: "b"
        - _id: "c"
      result: 3

# … would be equivalent to:
tests:
  - name: "Counting"
    documents:
      - _id: "a"
      - _id: "b"
    query: |
      count(*)
    result: 2

  - name: "Counting 2"
    documents:
      - _id: "a"
      - _id: "b"
      - _id: "c"
    query: |
      count(*)
    result: 3

Versioning

Each test can be tagged with a version field which should contain a version selector. The version is on the form X.Y and specifies that it targets GROQ-X.revisionY.

# This test file:
documents:
  - _id: "a"
  - _id: "b"

version: ">= 1.0"

tests:
  name: "Counting"
  query: |
    count(*)
  result: 2

The version 0.1 is used for the original implementation of GROQ before there was a finalized specification and is maintained here for historical reasons.

Variables

Queries can use the syntax ~name~ for referring to variables. Together with test inheritance this can be used to succinctly test many different cases.

documents:
  - _id: "a"
  - _id: "b"
  - _id: "c"

tests:
  - name: "Filtering"
    query: |
      count(*[~filter~])
    tests:
      - result: 1
        variables:
          filter: '_id == "a"'
      - result: 2
        variables:
          filter: '_id >= "b"'

Automatic test generation based on variables

To increase the test coverage we automatically generate extra test cases. The following test case,

tests:
  - name: "Compare"
    query: |
      ~str~ < "z"
    variables:
      str: ["a", "b"]

will generate the following additional test queries:

  • Plain: "a" < "z"
  • GenFilter: *[_id == "foo"][bar < "z"][]._id (and create the needed documents)
  • GenFetch: *[_id == "foo"][0].bar < "z" (and create the needed documents)
  • GenJoin: *[_id == "foo]{\"children\":*[_id == \"foo\"][^.f == f][]._id}" (and create the needed documents)

The rules of how the tests are generated are as follows:

  • If a test case has an explicit dataset (either documents or dataset) then nothing will be generated.
  • Every variable which contains valid JSON is eligable for automatic test generation.
  • We assume that every variable is standalone (e.g. we can safely pull them out). You can use standaloneVariables: ["var1"] in case there are some variables which are not standalone.
  • Set genFilter: false, genFetch: false and/or genJoin: false to disable the generated tests.

Features

A test can specify a list of named features that it requires, which a test runner can use to skip tests or enable specific modes. Currently defined features:

  • portableText: Functionality provided by the pt extensions.
  • geo: Functionality provided by the geo extension.
  • wildcardMatchSegmentation: Specifies a more sensible semantics for handling wildcards in the match operator.

Scores

Since the scoring algorithm used by score() is currently implementation-defined, tests cannot contain the literal score. Instead, tests must use an ordinal number to represent the position among the total list of result scores. The test runner, when comparing results, should replace the actual scores with this algorithm:

  • Take all encountered scores in the results
  • Remove duplicates
  • Sort them
  • Replace each score with an attribute _pos containing the position in the list

For example: If a query returns:

- {id: "a", _score: 1.0}
- {id: "b", _score: 1.2}
- {id: "c", _score: 1.2}
- {id: "d", _score: 1.4}

then these should be remapped as:

- {id: "a", _pos: 1}
- {id: "b", _pos: 2}
- {id: "c", _pos: 2}
- {id: "d", _pos: 3}

…and this is what the test needs to test equality against.

In other words, any value with equal score is given the same ordinal value.

Specifying datasets

Tests can either declare datasets inline (using the documents property) or refer to an external dataset by name:

dataset: movies
tests:
  - name: "Good movies"
    query: |
      count(*[_type == "movive" && rating > 8.0])
    result: 123

Currently the following named datasets are available:

Name Size Documentation URL
movies ~500k documents (~200MB) ./utils/the-movies-dataset 🔗

Schema

The full schema is as follows:

// Every test file contains a single "test"
type TestFile = Test

type Test = {
  dataset?: string
  documents?: Array<any>

  name?: string

  query?: string
  variables?: Variables

  result?: any
  valid?: boolean // defaults to `true`

  tests?: Array<Test>
}

type Variables = { [key: string]: string }

groq-test-suite's People

Contributors

atombender avatar dependabot[bot] avatar j33ty avatar judofyr avatar mwain avatar rneatherway avatar sgulseth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

fairhopeweb

groq-test-suite's Issues

license of groq test suite

Hello,

Is it possible to add a license file to this repo such that we know whether we can derive from it in our own repos?

I'd guess it will be MIT © Sanity.io to match sanity js.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.