3.0.12 • Published 11 months ago

trythistrythat v3.0.12

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
11 months ago

trythistrythat

Execute UNIT tests and generate coverage reports using c8 (embedded). ESModule.
( tttt | 4t | t8 ) available executables

⚠ not ready to be used in PRODUCTION environments.


Index of Contents


Description

TryThisTryThat it is a personal project to learn how a UNIT test framework can be built.
So far, I found it useful and well-structured.
It lacks simplicity to write unit test files, but that is something that will be improved.
I also wanted to learn how to develop a multi-thread application to run in parallel multi tests.
Since the beginning, where it was not making any use of workers-thread, the speed has clearly grown.

Basically, for every UNIT test file one worker-thread is spawned

Dependencies that make the application complete:

c8 to generate coverage reports.
cli-table3 to format the output of the results using table.

It has, few at this time, wrappers around node:assert functions.
Everything will be extended and improved.


Installation

⚠ Can it be installed globally? I haven't tried it yet.

npm install -D trythistrythat

simple usage

through a shell in the root directory of your project type the command below to add one UNIT test called first UNIT and having the filename as first.test.js
trythistrythat has the default directory as ./tests, it will make it and place the file in there.
default it is also the file extension to .ts, so to add a UNIT test as a javascript file, we need to pass the --extension flag set to .js

4t add --filename='first.test.js' --name='first UNIT' --extension='.js'

the created file will look like the one below.

import * as tttt from 'trythistrythat'

/**
 * Module filename - first.test.js
 *
 * @param {string} id - UNIT-test-identification random UUID
 * @returns {Promise<void> | void}
 */
export default async ( id ) => {
  // This is simple example with all the required function to make the UNIT test works fine.
  // Edit the file as your needs
  let error = false

  if( error ){
    tttt.failed( 'first UNIT' )
    tttt.end( id, false, 'first UNIT' )
  }else
    tttt.end( id, true, 'first UNIT' )
}

write down your own logic or/and, to give it a try, run the next command.

4t test --file='first.test.js'

▷ trythistrythat API is explained in detail here.


CLI commands & flags


commands


add

4t add --filename='my.test.js' --name='My Test' --twd='my custom tests directory'

Default tttt working directory (twd) is tests if not found the default working directory will be made. set it to something else if needed using the global flag --twd, MUST go before the command add, --twd='your path'.

The flags --filename and --name are optional, but recommended.


--filename(-fn)? = { string }

  • filename for the UNIT test.

--name(-n)? = { string }

  • name for the UNIT test.

--extension(-ext)? = { string }

  • filename extension for the UNIT test.

--imports?(-i) = { options }

  • a list of imports to declare in the UNIT test.

4t add -n='my test with imports' -fn='my.test' -i='{writeFile}:fs|{oftype_}:oftypes' -ext='.js'

the created UNIT will look like this

import * as tttt from 'trythistrythat'
import { oftype_ } from 'oftypes'
import { writeFile } from 'fs'

/**
 * Module filename - my.test.js
 *
 * @param {string} id - UNIT-test-identification random UUID
 * @returns {Promise<void> | void}
 */
export default async ( id ) => {
  // This is simple example with all the required function to make the UNIT test works fine.
  // Edit the file as your needs
  let success = true

  if( success )
    tttt.end( id, true, 'my test with imports' )
  else{
    tttt.failed( 'my test with imports' )
    tttt.end( id, false, 'my test with imports' )
  }
}

--tttt-working-dir?(-twd) = { string }

  • set default working dir to the specified path.

conf

A set of utilities to deal with configuration files of the whole application.

⚠ only the management of the ignore file at the moment.


ignore utilities:

By creating an 'ignore' file, trythistrythat will parse the excluded files|directories ignoring them to be executed as a UNIT test.
Using the global flag, --no-parse-ignore-file, the parsing of this file will be skipped.

4t conf --create-ignore='filename-name-to-ignore'
4t conf --insert-ignore-entry='filename-name-to-ignore'
4t conf --delete-ignore-entry='directory'

--create-ignore (-ci) = {string}

  • creates and adds one entry (file | directory) to the .ttttignore file.
  • it is required to pass an entry.

--insert-ignore-entry (-iie) = {string}

  • adds one entry (file | directory) to the .ttttignore file.
  • it is required to pass an entry.

--delete-ignore-entry (-die) = {string}

  • deletes one entry (file | directory) to the .ttttignore file.
  • it is required to pass an entry.

remove

removes one UNIT test file | directory

⚠ When removing one directory, be aware that it doesn't ask for confirmation.

4t remove --filename='my.test.js' #to remove one file
4t remove --filename='path/to/directory' #to remove one directory

--filename (-fn) = { string }-

  • to remove the provided filename|directory.

--tttt-working-dir?(-twd) = { string }

  • set default working dir to the specified path.

test

Run a test for a UNIT filename or for an entire directory. The flags --directory && --file cannot be called in the same time.
The flag --exclude make sense only when used with --directory.


--file (-f) = { string }

  • Unit test filename
  • it is mandatory to pass an argument

--directory (-d) = { string }

  • Scan recursively a specific directory for UNIT test file.
  • it is mandatory to pass an argument.

--exclude (-e)= { string }(comma separated value)

  • exclude specified directories of filenames.
  • only for command 4t test --directory='my directory test to scan'

--tttt-working-dir?(-twd) = { string }

  • set default working dir to the specified path.

unit

Recursively scans the twd (trythistrythat working directory) and runs all the found UNITS.


--exclude (-e) = { string }(comma separated value) -

  • exclude specified directories of filenames.

--tttt-working-dir?(-twd) = { string }

  • set default working dir to the specified path.

update

It checks for any update available, for trythistrythat (in the future also about other dependency of the project), and informs if there is any.
Default it checks only without installing. Anyway, asks if it is intended to install it.

4t.js update --y # it checks and installs the update

--y

  • it instructs the update command to install the updates, if any, without asking for confirmation.

version -v

it shows the current version of trythistrythat


global flags

There are still a few global flags that MUST be placed before the desired command

  1. --c8
  2. --no-parse-ignore-file
t8 --c8 unit --exclude='one directory'

--c8

  • instructs 4t to run the UNIT test with coverage, activating c8.
  • in this case, the t8 executable of trythistrythat will be used.
  • by Default, c8 will skip units with full coverage.
t8 --c8 unit # it execute c8 with the default options.

--no-parse-ignore-file {void}

  • it instructs trythistrythat to do NOT parse the .ttttignore file.

tttt API

These functions, below described, are meant to be called in the AsyncFunction of the UNIT test file.


tttt.end

tttt.end( { string } id, { boolean } success = true ?, { string } name ?, { string } message ?) => fires tttt.event.end

this function is mandatory to be placed in any of the async functions declared in the UNIT test.

run the command

4t add --filename='match.test.js' --name='match assertion' --extension='.js' --imports='assert:assert/strict'

replace all the generated code with the one below except for the imports

import * as tttt from 'trythistrythat'
import assert from 'node:assert/strict'

/**
 * Module filename - match.test.js
 *
 * @param {string} id - UNIT-test-identification random UUID
 * @returns {Promise<void> | void}
 */
export default async( id ) => {
  let error = undefined
  try{
    assert.match( 'trythistrythat', /assert/, 'true' )
  }catch ( match_error ) {
    error = match_error.message
  }
  
  if( error === 'false' )
    tttt.failed( 'match assertion' )
  
  // the {id} variable is mandatory, but must be always passed to the async function of the unit test, so no need to worry.
  // the {success} variable can be omitted and by default will considered true
  // the {name} variable can be omitted and it will be replaced by #noname UNIT, if it is given the output of the result appears more clear.
  // the {message} variable can be omitted but if given it will show an extra row in the table output. usefull to explain what the test is doing.
  tttt.end( id, error === 'true', 'match assertion', 'example on how to use node:assert to run trythistrythat' )
}

now run the command and the output will be something like this

4t test --file=match.test.js
┌─────────────────┬────────────────┬────────┬────────────────┬───────────────┐
│ name            │ execution time │ status │ ID             │ filename      │
├─────────────────┼────────────────┼────────┼────────────────┼───────────────┤
│ match assertion │ 0.465041ms     │ [OK]   │ (ID)[111f6e5d] │ match.test.js │
├─────────────────┴────────────────┴────────┴────────────────┴───────────────┤
│ example on how to use node:assert to run trythistrythat                    │
└────────────────────────────────────────────────────────────────────────────┘
---------------------------------------------------------------------------
overall execution time | 0.465041ms | exit with code:  0
---------------------------------------------------------------------------

tttt.failed

tttt.failed( { string } name ? ) => void

this function is mandatory to be placed in any of the async functions declared in the UNIT test.

simply this will push the name of the unit test that has failed, and it will be output at the bottom of the test result to easily know which UNIT test has thrown the error.

use it with tttt.end to also update the table output result.

if(error instanceof Error){
  tttt.failed( 'name of the unit test' )
  tttt.end( id, false, 'name of the unit' )
}
  

tttt.resolvers

tttt.resolvers( { any } actual, { any } expected, { string } error_message ? = undefined ) => { Object< actual: any, expected: any, error_message: string > }

Resolvers for node:assert wrapped functions.

import * as tttt from 'trythistrythat'

export default async ( id ) => {
  
  let success = true
  const result = tttt.ok( async ()=>{
    
    const actual = true
    const expected = true
    const error_message = 'assert.ok thrown an exception' // this is going to replace the assert.ok AssertionError.message
    return resolvers( actual, expected, error_message )
  } )
  
  if(result instanceof Error) {
    tttt.failed( 'my suite' )
    success = false
  }
  
  tttt.end( id, success, 'my suite', result.message )
  
}

embedded c8

The c8 package is now embedded and optimized to run asynchronously.

⚠ work in progress to make you pass all the available options to the embedded version. for the moment is tailored.

⚠ check the package.json scripts to see how it works to pass options for it.

Special thanks to the team behind it.

available options and how to pass it to the CLI

  • c8 available flags

all

the same as the c8 CLI

src

the same as the c8 CLI

skip-full

the same as the c8 CLI

html

if passed c8 will generate lcov and html reports

  • t8 available flags

no-print

if passed t8 will not print the result to stdout

no-questions

if passed t8 will NOT ask some questions

how to pass the flags

# all the flags that do not have any argument must me followed by : and |
t8 --c8='all:|skip-full:|src:./src|html:|no-questions:|no-print:' unit

Contributing

fork the repository follows the guidelines

have it locally required to be built and tested for any new functionality

into the package.json -> scripts file you have everything to begin with.

the files:
1. ./4t.js 2. ./t8.js 3. ./bin/c8.js

⚠ those files above, once compiled, must be given a chmod u+x

the command npm run build does everything.

npm install && npm run build

commit and make a pull request.


JetBrains OSS License

I want to thank JetBrains to grant me the Open Source Software license for all their products. This opportunity gives me strength to keep on going with my studies and personal project.
To learn more about this opportunity, have a look at Licenses for Open Source Development - Community Support.

Thank you


Contacts

  • twitter
  • open-collective

3.0.12

11 months ago

3.0.10

12 months ago

3.0.11

12 months ago

3.0.8

1 year ago

3.0.7

1 year ago

3.0.6

1 year ago

3.0.5

1 year ago

3.0.9

1 year ago

2.0.3

1 year ago

2.0.2

1 year ago

2.0.5

1 year ago

2.0.4

1 year ago

2.0.7

1 year ago

2.0.6

1 year ago

2.0.1

1 year ago

2.0.0

1 year ago

3.0.4

1 year ago

3.0.2

1 year ago

3.0.1

1 year ago

3.0.0

1 year ago

1.9.5

1 year ago

1.9.4

1 year ago

1.9.3

1 year ago

1.9.2

1 year ago

1.9.1

1 year ago

1.9.0

1 year ago

1.8.18

1 year ago

1.8.9

2 years ago

1.8.10

2 years ago

1.8.8

2 years ago

1.8.11

2 years ago

1.8.7

2 years ago

1.8.12

2 years ago

1.8.13

2 years ago

1.8.5

2 years ago

1.8.14

2 years ago

1.8.4

2 years ago

1.8.15

2 years ago

1.8.16

2 years ago

1.8.17

2 years ago

1.8.2

2 years ago

1.6.4

2 years ago

1.8.1

2 years ago

1.6.3

2 years ago

1.4.5

2 years ago

1.8.0

2 years ago

1.6.2

2 years ago

1.4.4

2 years ago

1.6.1

2 years ago

1.4.3

2 years ago

1.6.0

2 years ago

1.4.2

2 years ago

1.2.4

2 years ago

1.4.1

2 years ago

1.2.3

2 years ago

1.4.0

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.1.1

2 years ago

0.1.30

2 years ago

1.1.0

2 years ago

1.5.3

2 years ago

1.7.0

2 years ago

1.5.2

2 years ago

1.5.1

2 years ago

1.5.0

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

0.1.27

2 years ago

0.1.28

2 years ago

0.1.24

2 years ago

0.1.25

2 years ago

0.1.26

2 years ago

1.6.6

2 years ago

1.8.3

2 years ago

1.6.5

2 years ago

0.0.10

2 years ago

0.0.11

2 years ago

0.0.12

2 years ago

0.0.13

2 years ago

0.0.14

2 years ago

0.0.15

2 years ago

0.0.16

2 years ago

0.0.8

2 years ago

0.0.17

2 years ago

0.0.5

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago