Giter Club home page Giter Club logo

pdtest's Introduction

Pure Data testing external

Async Functional testing for Pure Data using Lua scripting.

PdTest is intended at developers of Pure Data externals that needs functional testing for their project. Functional tests are organised as test suites, grouping test cases that coordinates the many individual tests. The pdtest external features mandatory inlet type creation arguments, adding test inlets for receiving results of the specifed types, while the active left inlet is used for loading test suites, starting, stopping and resetting the test loop. Test are built using standard Lua scripts, with provided helper functions for declaring the test structure. Refer to Lua documentation to learn more about test scripts syntax.

Test Suite Syntax:

Building a test suite is easy when you know its basics:

Suites functions

mysuite = Suite("my test suite")
mysuite.setup(function()                                -- set a setup function to be called
    _.outlet({"SOME","SETUP","MESSAGE"})                -- before all of this suite tests
end)
mysuite.teardown(function()                             -- set a cleanup function to be called
    _.outlet({"SOME","CLEANUP","MESSAGE"})              -- after all of this suite tests
end)
mysuite.case("my test case")                            -- define a new test case

Cases functions

mycase = mysuite.case("my test case")
mycase.setup(function()                                 -- set a setup function to be called
    _.outlet({"SOME","SETUP","MESSAGE"})                -- before all of this case tests
end)
mycase.teardown(function()                              -- set a cleanup function to be called
    _.outlet({"SOME","CLEANUP","MESSAGE"})              -- after all of this case tests
end)
mycase.test({"MY","TEST","MESSAGE"})                    -- lua table as pd list message to outlet
mycase.test("MESSAGE")                                  -- lua string as pd symbol message to outlet
mycase.test(3.1416)                                     -- lua number as pd float message to outlet
mycase.test(function(test)                              -- long test form, function body can contain only one
    test({"MY","TEST","MESSAGE"})                       -- test() call, but unlimited _.outlet().
end)

Tests functions

mycase.test({"MY","TEST","MESSAGE"}                     -- tests are made by calling condition methods
    ).should:equal(                                     -- like equal() from the .should namespace
        {"TEST","DESIRED","OUTPUT","MESSAGE"})          -- notice the colon for calling condition methods
mycase.test({"MY","TEST","MESSAGE"}                     -- tests can also be reversed by calling them
    ).should.nt:equal(                                  -- from the .should.nt namespace
        {"TEST","NOT","DESIRED","OUTPUT","MESSAGE"})

Conditions methods

equality

.should:equal(                                          -- equal method test for message content equality
    {"TEST","DESIRED","OUTPUT","MESSAGE"})
.should.nt:equal(                                       -- not equal method
    {"TEST","UNDESIRED","OUTPUT","MESSAGE"})

similarity

.should:resemble(                                       -- resemble is close to equal, 2 list will resemble if 
    {"SOME","MESSAGE","LIST"})                          -- they have the same members even with different indexes,
                                                        -- numbers will be rounded according to a decimal precision
.should:resemble(26.6666, 3)                            -- argument, strings will match event when case differs,
                                                        -- a number and a string will match if their string values
.should.not:resemble(                                   -- are equal and strings or numbers will match a tables first
    {"SOME", "OTHER", "MESSAGE", "LIST"})               -- member

possibility

.should:be_any({"A","B","C"})                           -- passes if any of the table's members equals the returned value
                                                        -- tables of tables are allowed to match table results
.should.nt:be_any({{1,2,3},{2,3,4},{3,4,5}})            -- not be any_

pattern matching

According to Lua’s pattern matching syntax

.should:match("%d+%s%a+")                               -- match method matches individual result atoms
.should.nt:match("%d+%s%a+")                            -- not match method

numeric comparisons

>
.should:be_more(10)                                     -- the greater than test, all four examples are equivalent
.should:be_more("10")                                   -- and results are treated in a similar manner.  Everything gets
.should:be_more({10})                                   -- converted to number and in the case of list only the first
.should:be_more({"10"})                                 -- is compared
.should.nt:be_more(22)                                  -- negation works as well
<
.should:be_less(10)
.should:be_less("10")
.should:be_less({10})
.should:be_less({"10"})
.should.nt:be_less(22)
>=
.should:be_more_or_equal(10)
.should:be_more_or_equal("10")
.should:be_more_or_equal({10})
.should:be_more_or_equal({"10"})
.should.nt:be_more_or_equal(22)
<=
.should:be_less_or_equal(10)
.should:be_less_or_equal("10")
.should:be_less_or_equal({10})
.should:be_less_or_equal({"10"})
.should.nt:be_less_or_equal(22)

custom truth

.should:be_true(function(result)                        -- be_true method test if provided function returns
    if result[1] == "OK" then                           -- true or false
        return true
    else
        return false
    end
end)
.should.nt:be_true(function(result)                     -- not be_true (be_false...)
    if result[1] == "ERROR" then
        return true
    else
        return false
    end
end)

The test namespace

A test function is made available as only argument inside the test function for sending test messages through the pdtest outlet. Specifically used inside a function() passed to the case.test() function. These messages are registered as test messages, pdtest will expect a test result for each of these test messages. General rule: 1 test call for each case.test().

test({"YOUR","MESSAGE","LIST"})               -- sends lua table as test message list through outlet
test("STRING")                                    -- sends lua string as test message symbol through outlet
test(3.1416)                                      -- sends lua number as test message float through outlet
test("BANG")                                      -- sends bang as test message through outlet

The _ namespace: direct pd calls

_.post("string to post")                          -- post to pd console
_.error("string to signal")                       -- sends error to pd console
_.outlet                                          -- namespace for sending untested messages to the pdtest outlet 

The _.outlet namespace → untested messages

Sending raw messages through the pdtest outlet. These unregistered messages go unnoticed through the test system. Meant to be used inside setup()/teardown() or as test helpers inside case.test() function()_. General rule: 1 ignored inlet message for each *.outlet* call.

_.outlet({"YOUR","MESSAGE","LIST"})             -- sends lua table as raw message list through outlet
_.outlet("STRING")                                -- sends lua string as raw message symbol through outlet
_.outlet(3.1416)                                  -- sends lua number as raw message float through outlet
_.outlet("BANG")                                  -- sends bang as raw message through outlet

Example Tests Suite

examplesuite.lua
mysuite = Suite("TestSuite") -- initializing a new test suite named "TestSuite"
mysuite.setup(function()                -- called before every test in the suite
  _.outlet({"command","flushdb"})
end)
mysuite.teardown(function()             -- called after every test in the suite
  _.outlet({"command","flushdb"})
end)
mysuite.case("Server Info"              -- new test case named "Server Info"
  ).test({"command", "INFO"}            -- will output message "list command INFO"
    ).should:match("^redis_version")    -- test will pass if result received on right 
                                        -- inlet starts with the string "redis_version"
mysuite.case("Reality Check"            -- second test case named "Reality Check"
  ).test({"command", "dummy"}           -- will output message "list command dummy"
    ).should:match("ERR"                -- test will pass if result received on right
  ).test({"command", "dbsize"}          -- inlet match the string "ERR"
    ).should.nt:match("ERR")            -- second test will pass if result doesn't match "ERR"
mycase = mysuite.case("Basic tests")    -- new test case named "Basic tests"
mycase.setup(                           -- called before every test in the case
  function() _.outlet({"command","SET","FOO","BAR"})
end)
mycase.test({"command", "GET", "FOO"}   -- test will pass if result equals "BAR"
  ).should:equal("BAR")
mycase.test(function(test)              -- here a test function is passed instead
  _.outlet({"command","DEL","FOO"})         -- notice its only argument being a test function
  test({"command","EXISTS","FOO"})
end).should:equal(0)
mycase.test(
  {"command","SETNX","FOO","BAT"}
  ).should:be_true(function(result)     -- test method '.should:be_true' takes a function
    if result == 1 then                 -- for which it provides a 'result' argument
      return true                       -- the function must return true or false
    else
      return false
    end
  end)
pd console
pdtest: loading testfile examplesuite.lua
pdtest: TestSuite -> Server Info < command, INFO > 
pdtest: -> OK
pdtest: TestSuite -> Reality Check < command, dummy > 
pdtest: -> OK
pdtest: TestSuite -> Reality Check < command, dbsize > 
pdtest: -> OK
pdtest: TestSuite -> Basic tests < command, GET, FOO > 
pdtest: -> OK
pdtest: TestSuite -> Basic tests < function > 
pdtest: -> OK
pdtest: TestSuite -> Basic tests < command, SETNX, FOO, BAT > 
pdtest: x> FAILED |> 0 is not true function
pdtest: !!! Test Completed !!!
pdtest: 1 Suites | 3 Cases | 6 Tests
pdtest: 5 tests passed
pdtest: 1 tests failed

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.