8000 GitHub - nik312123/testy: Test running script in a bash script file
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

nik312123/testy

 
 

Repository files navigation

Testy

A script to run tests for interactive terminal programs. Tests are specified in Emacs Org-like files.

Usage

Usage is best described by the help message shown via testy --help (which is the text at the top of the testy source:

usage:    testy <testfile.org> [test# test# ...]
          testy --help

examples: testy test_prob1.org          # runs all tests in file
          testy test_prob1.org 3 5 7    # runs tests 3,5,7 in file
          testy test_prob1.org 5        # runs only test 5 and shows failures to stdout
          SHOW=1 testy test_prob1.org   # runs tests and prints all failures to stdout
          DEBUG=1 testy test_prob1.org  # runs printing LOTS of debug messages

Run tests for a shell program specified in an org-like file and report
the results.


----------------------------------------
--- RUNNING TESTS ---
----------------------------------------

Running a test is done from the command line and will default to
running all tests in a provided test file. Output shows each test with
a pass/fail and failures have results files indicating what went
wrong. Below is an example from the examples/ directory:

>> cd examples/
>> ../testy bash_tests.org
============================================================
== testy bash_tests.org
== Running 2 / 2 tests
1)  Output Tests         : ok
2)  Failure Demo         : FAIL -> results in file 'test-results/test-02-result.tmp'
============================================================
RESULTS: 1 / 2 tests passed

Inspecting the failure file indicated (always under freshly created
directory 'test-results/' ) shows the following output (plain text but
easier easier to read in org-mode):

----------------------------------------
>> cat test-results/test-02-result.tmp
* (TEST 2) Failure Demo
COMMENTS:
This test will fail and produce output associated to show the
side-by-side diff that primarily reports failures.

** program: bash -v
To run this individual test in GDB use the command:
  gdb --args bash -v
but any input to the program must be typed within the debugger

** --- Failure messages ---
- FAILURE: Output Mismatch at lines marked

** --- Side by Side Differences ---
- Expect output in: test-results/raw/test-02-expect.tmp
- Actual output in: test-results/raw/test-02-actual.tmp
- Differing lines have a character like '|' '>' or '<' in the middle
#+BEGIN_SRC sbs-diff
==== EXPECT ====                        ==== ACTUAL ====
>> echo "Matching Line"                 >> echo "Matching Line"
Matching Line                           Matching Line
>> echo "Mismatching Line"              >> echo "Mismatching Line"
Misma____ Li__                        | Mismatching Line
>> echo "Extra line in ACTUAL"          >> echo "Extra line in ACTUAL"
                                      > Extra line in ACTUAL
>> echo "Extra line in EXP
95E7
ECT"          >> echo "Extra line in EXPECT"
This is the extra line                <
Extra line in EXPECT                    Extra line in EXPECT
>> printf "Matches fine\nAnd again\n"   >> printf "Matches fine\nAnd again\n"
Matches fine                            Matches fine
And again                               And again
#+END_SRC

** --- Line Differences ---
EXPECT:   4) Misma____ Li__
ACTUAL:   4) Mismatching Line
ACTUAL:   6) Extra line in ACTUAL
EXPECT:   7) This is the extra line
----------------------------------------

The main section in the middle of the file is a side-by-side diff of
expected and actual output with the center column indicating what
differences were detected.  Generally whitespace differences are
ignored.


----------------------------------------
--- TEST FILE FORMAT ---
----------------------------------------

Tests are specified in org-like files. Each top-level section starts
with a * with a test title, followed by comments and test sessions of
input/output. Each test can have multiple sessions. As a session is
found it is run. If the session fails, subsequent sessions for that
test are not run.

Sample input file (sample_tests.org):
----------------------------------------
#+TITLE: Sample Tests

* Test echo
Check that the 'echo' command in bash is working.

The org-mode 'sh' param is not honored in testy; it is for easy
editing/formatting in Emacs but does not reflect what program will
actually run the and can be replaced with whatever.

#+BEGIN_SRC sh
>> echo 'hello'
hello
>> echo 'Hi there!'
Hi there!
#+END_SRC

* Test printf, will fail
Tests whether printf works.

#+BEGIN_SRC sh
>> printf "Hello world\n"
Hello world
>> printf "Multi-line\noutput is expected\nhere\n"
Multi-line
output is expected
here
>> printf "%s\n" "substitute me"
substitute me
#+END_SRC

This second session below will fail (intentionally) as the output of
the printf will not match the expected output. The results of the
failure will be in a file which is listed by testy as the tests run.
#+BEGIN_SRC sh
>> echo 'hi'
hi
>> printf 'INTENTIONAL fail\n'
INTENTIONALly fails
#+END_SRC

* Test bc
This test uses a different interpreter than the standard 'bash'. The
'bc' program interprets standard mathematical expressions. Note the
use of #+TESTY expression to change the program for this test.

#+TESTY: program="bc -iq"
#+BEGIN_SRC sh
>> 1+1
2
>> 3*5+12
27
#+END_SRC
----------------------------------------

Running the command './testy sample_tests.org' will produce output like the following:

----------------------------------------
> ./testy sample_tests.org 
============================================================
== sample_tests.org : Sample Tests
== Running 3 / 3 tests
1)  Test echo              : ok
2)  Test printf, will fail : FAIL -> results in file 'test-results/test-02-result.tmp'
3)  Test bc                : ok
============================================================
RESULTS: 2 / 3 tests passed
----------------------------------------

The file listed will will contain information on the failure.



----------------------------------------
--- BEHAVIOR / ENVIRONMENT VARIABLES ---
----------------------------------------

The following variables can be specified in test files via lines like
  #+TESTY: var="value"
or via an environment variable during a program run as in
  > VAR="value" testy testfile.org
or via exporting an environment variable as in
  > export VAR="value"
  > testy testfile.org

They will change the behavior of how the test data is interpreted.

GLOBAL VARIABLES that are usually specified at the beginning of a test
file before any other tests.

PROGRAM="bash -v"         : program to run/test; input is fed to this program
PROMPT=">>"               : prompt that indicates input to the program
ECHOING="input"           : {input, both} for program input echoing style,
                            "input" means the program echoes only input provided by testy, testy will add back in prompts
                            "both" echoes both prompt and input so testy won't add back anything
                             NOTE: testy does not support mocked interaction tests for programs that don't echo input
                             as this is generally hard to do
PREFIX="test"             : prefix for test output files, often changed to reflect program name like 'myprog'
RESULTDIR="test-results"  : directory where the results will be written
RESULTRAW="RESULTDIR/raw" : directory where actual / expect / valgrind results are stored
TIMEOUT="5s"              : maximum time to complete test before it is failed due to timeout; passed to the 'timeout' utility
POST_FILTER=""            : program to adjust output from test before evaluating, run as 'cat output | post_filter > actual.tmp'
USE_VALGRIND="0"          : set to 1 to run programs under Valgrind which checks for memory errors; useful for C programs especially
VALGRIND_REACHABLE="1"    : under valgrind, report errors if memory is still reachable at the end of the program
VALGRIND_OPTS=""          : pass additional options to valgrind such as '--suppressions=test_valgrind.supp' to use a suppression file
SKIPDIFF="0"              : skip diffing results, useful if checking only valgrind with actual output varying between runs
USE_POINTS="0"            : set to 1 to assign points to tests and report the total rather than a count of passed tests
POINTS="1"                : number of points assigned to each tests; only integer values are supported

Each of the above Global variables can be set Locally during a single
test by setting their lower-case version. For example:

  * Test 5: A test of bc
  #+TESTY: points="3"
  #+TESTY: program="bc -i"

will send input to the program "bc -i" and check output rather than
the default PROGRAM. The lower case options are reset during each test
run but NOT in between sessions in single test.

Finally, these variables control some global behavior of the testy.
SHOW=0            : set to 1 to print test error results after completing
DEBUG=0           : set to 1 to print LOTS of debugging messages
REPORT_FRACTION=0 : report the fraction of tests passed rather than the count
SCALE_POINTS=0    : set to non-zero / fractional value to scale the total points earned / available (e.g. SCALE_POINTS=0.5)


----------------------------------------
--- TESTY MULTI ---
----------------------------------------

Standard tests are for a single program running at a time. If several
programs need to run concurrently and coordinated during a test, one
can use the special program line
  #+TESTY: PROGRAM='TESTY_MULTI'
for all tests or
  #+TESTY: program='TESTY_MULTI'
for a single test.

The test itself then takes as input a series of commands which dictate
when to start programs, feed them input, sned them signals, and wait
for them to shut down.

--- TESTY_MULTI Commands are (briefly) ---
- START <key> <program> [args]
  >> START server ./banter_server gotham      # runs program 'banter_server gotham' and refers to it via key 'server'
  >> START bruce ./banter_client gotham bruce # runs program 'banter_client gotham bruce' and refers to it via key 'bruce'

- SIGNAL <key> <sigspec>
  >> SIGNAL server -15                        # sends program w/ key 'server' signal 15 (TERM)
  >> SIGNAL bruce -INT                        # sends program w/ key 'server' a keyboard interrupt signal (15)

- INPUT <key> text text text
  >> INPUT bruce Robin? Barbara?              # sends text input to program w/ key 'bruce'
  >> INPUT clark <EOF>                        # sends End of Input to program w/ key 'clark'

- WAIT <key>
  >> WAIT server                              # causes testy to wait for program w/ key 'server' to complete

- WAIT_ALL
  >> WAIT_ALL                                 # waits for all programs to complete

- OUTPUT <key> <filter>
  >> OUTPUT server cat                        # testy prints the output for program w/ key 'server' passing to through filter 'cat'
  >> OUTPUT bruce ./test_filter_client_output # ditto but passes through the specified filter program

- OUTPUT_ALL
  >> OUTPUT_ALL cat                           # testy prints output for all programs for comparison in the test results; filtered through 'cat'
  >> OUTPUT_ALL ./test_filter_client_output   # ditto but passes through the specified filter program

- CHECK_FAILURES <key> <filter>
  >> CHECK_FAILURES server cat                # for 'server', prints any failures like timeout, non-zero return, valgrind problems, etc. 
                                              # prints nothing if no failures detected

- CHECK_ALL <filter>
  >> CHECK_ALL cat                            # checks failures in all programs that are part of test passing through 'cat' as a filter

- SHELL cmd cmd cmd
  >> SHELL rm some-file.txt                   # runs a shell command in the middle of the test in this case removing a file
----------------------------------------

An example of a TESTY_MULTI testing file is in

  testy/examples/banter_tests.org

which tests a tiny chat server/client written in bash. A server is
started and several clients 'join' the server and exchange messages.

TESTY_MULTI has a few more control global variables to dictate
behaviors specific to it.

TICKTIME="0.1"            # amount of time to wait in between test commands during a TESTY_MULTI session
VALGRIND_START_TICKS="8"  # number of ticks to wait during TESTY_MULTI when starting a program under valgrind
                          # valgrind slows things down so it takes more time for programs to start up

Depending on system speed, one may wish to lengthen these parameters
through setting them globally at the top of the testy file as in:
  #+TESTY: TICKTIME=0.1
  #+TESTY: VALGRIND_START_TICKS=8


----------------------------------------
--- CAVEATS ---
----------------------------------------

testy is in ALPHA stage and actively being developed. For that reason
no guarantees are made about its reliability. Especially TESTY_MULTI
sessions have some known failings not to mention the fact that relying
on a tick time to coordinate programs is doomed to fail at some point.

All the same, enjoy!
- Chris

License

testy is released under the terms of the GNU General Public License v3.0-or-later (GPLv3-or-later). A copy of the GPLv3-or-later is included in the file LICENSE in the source repository.

Planned and Completed Additions

See file:NOTES.txt which contains notes on planned and completed additions

Install macOS Requirements

Note: testy is primarily supported for Linux/GNU.

The installation script of testy dependencies for macOS (install_mac_requirements.sh) is made by a macOS contributor and does not guarantee that testy will work on macOS for all use cases.

The goal of the install_mac_requirements.sh script is to install the dependencies required for testy to work on macOS. At this time, due to lack of proper valgrind support on macOS, the aforementioned script does not install valgrind As such, use_valgrind should be set to 0 in .org files that testy runs like the following: #+TESTY: use_valgrind=0

To run the above installation script, you may run the following:

bash <( curl -fsSL "https://raw.githubusercontent.com/kauffman77/testy/master/install_mac_requirements.sh" )

To run the script in verbose mode (prints commands being run and their outputs) add the -v flag like so:

bash <( curl -fsSL "https://raw.githubusercontent.com/kauffman77/testy/master/install_mac_requirements.sh" ) -v

You may also simply download the script and run it as follows:

# Normal
./install_mac_requirements.sh

# Verbose
./install_mac_requirements.sh -v

Note that the script can be run again without issue. It will automatically detect what is already installed and will not reinstall them again.

Rather, it will ensure that all of the installed components are up to date!

About

Test running script in a bash script file

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Shell 72.4%
  • Python 27.5%
  • Makefile 0.1%
0