Giter Site home page Giter Site logo

codehearts / shpy Goto Github PK

View Code? Open in Web Editor NEW
13.0 4.0 3.0 161 KB

🕵️‍♀️ POSIX compliant spies and stubs for shell unit testing

Home Page: https://hub.docker.com/r/shpy/shpy

License: MIT License

Shell 97.07% Dockerfile 2.93%
shell testing shunit2 mocks stubs posix hacktoberfest

shpy's People

Contributors

codehearts avatar mkropat avatar operationalfallacy avatar renovate-bot avatar renovate[bot] avatar tom-rb avatar yeeplusplus avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

shpy's Issues

Ignore common warnings with shellcheck

Shellcheck warns about using local, but there's no problem with us using it. That warning should be disabled in our default invocation of shellcheck.

Also take this chance to set up shellcheck with HoundCI. We'll need a .hound.yml and a yaml file for the shellcheck warnings to ignore

Infamous trailing spaces in wc util on mac

Hi,

Thanks for an amazing framework, it helped me refactoring tons of shell scripts that overwise were hopeless.

I run into small issues while developing on Mac. The wc util has a nasty behavior on Macs where its return contains leading spaces, as described here https://stackoverflow.com/questions/30927590/wc-on-osx-return-includes-spaces

This makes the output of _shpyGetDirectoryContentsCount function incorrect, which breaks counts when there are multiple spy calls.

I can submit PR, but I'd like to know if this is something worth fixing. I guess people may run into this if they develop on Macs?

Thanks!

Add call-through option

When a spy is invoked, record the arguments it was invoked with and then execute (call through to) the original function/command.

This will only ever work with a shell that supports something like declare -f or typeset -f, so dash and posh support is a no-go.

Shpy doesn't support spies in separate shell processes

Discovered this while writing practical use examples for new users. Shpy works great for shell libraries you source into a script, but is unable to handle executable shell scripts which run in a separate shell process

Modify shpy to support this case. I have a feeling it might be one of the more common use cases

Detail how shpy works in contributing.md

It would be really nice to have a simplified overview of how shpy works, how it creates the stubs, how it tracks calls, stubs outputs, etc. This should go in the development section of contributing.md

Question about nested functions calls

I was looking how to refactor ol’ scripts without too much rewriting and have functions there tested separately. The easiest way was to source target script (with some logic to prevent it running everything) and then do usual spy/asserts for each function.

However, if functionA calls functionB which calls functionC - then spy for functionB is ignored because I think bash first calls sourced functions and then one in PATH.

Workaround is to remove all nested functions with ‘unset -f functionB’ inside each test.

I wonder if that’s something framework can handle, maybe with a flag?

Investigate storing spy outputs in memory

Spy output is currently stored on disk, but they could theoretically be stored in memory as _shpy_${spy_name}_stdout_${index} to avoid disk access

Try looking into the following:

  • Can a proof of concept be made for this?
  • Should this be hidden behind a SHPY_RUN_MODE=memory|disk flag, or made default?
  • What impact does this have on runtime of shpy's tests?

Don't forget to update CONTRIBUTING.md to detail the new inner workings!

Ensure shpy Docker image is pushed/pulled once every 6 months

Docker is introducing an image retention policy for free plans (of which the shpy organization on Docker Hub is) that will remove images which have not been pushed or pulled in 6 months. I agree with the policy of removing unused images, but would like shpy to hang around for developers who discover it to have easy access

I haven't checked if this is really an issue or not (I'm not sure how often our image is used), but worst case we can always auto-publish every few months. I think this makes sense, too, because we'll automatically be kept up to date with the latest versions of supported shells

Publish a container for shpy

Once #15 is done, publish Docker containers for each release and for the latest master node. The container should make it easy for devs to test their scripts with shpy and shunit2 under the more common shells (sh, dash, bash, zsh, maybe fish? ksh? csh?)

More 'undefined' vars checks

There are three more instances where undefined variables aren't checked in a way that works with the nounset flag

Example (dummy_test):

testDummy() {
  set -o nounset
  cleanupSpies
}

Output:

# dummy_test: 147: eval: _shpy_spies_dir: parameter not set

The other two instances involve createSpy: if a return value is passed via -r, and if no spy name is passed

Support output via STDERR

I'm trying to stub a function which prints its expected output to STDERR, but it doesn't look shpy supports this. Would it be reasonable to add an -e STDERR_OUTPUT option, which would be printed in addition to output from -o?

Get the actual arguments passed to the mock for a particular call

It would be nice to have a way to get the actual arguments that were passed to the mock for call X

For example:

createSpy some_spy
    
some_spy foo
some_spy
some_spy bar -a foo -baz

getArgsForCall some_spy 1
# foo

getArgsForCall some_spy 2
#

getArgsForCall some_spy 3
# bar -a foo -baz

Enforce coding styles

I've been working with Rust lately, and having rustfmt reformat code has been a godsend. I've noticed shpy has differing indentation levels and coding styles from file to file, it'd be nice to run and enforce shfmt for consistency

Support return value sequences

I'm really liking shpy so far, especially its support for subshells! I have a function which calls a stub multiple times, and I'm not able to test cases where the stub returns a different value on subsequent calls.

My thought would be supporting a createSpy -r 0 -r 1 -r 2 spyName syntax, and always return the last value after finishing the sequence.

Use Docker Compose for testing

Testing uses like, 5 or 6 different Docker images. Docker Compose would manage these for us, provide parallel pulls, and perform parallel testing with output that can be filtered as needed all under docker-compose up

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

docker-compose
docker-compose.yml
dockerfile
Dockerfile
  • koalaman/shellcheck v0.8.0
  • alpine 3.17.3
  • kcov/kcov v40
  • alpine 3.17.3
github-actions
.github/workflows/test.yml
  • actions/checkout v3
  • actions/checkout v3
  • codecov/codecov-action v3

  • Check this box to trigger a request for Renovate to run again on this repository

Tag releases with semver

As a dependency for developers looking to test their scripts, it's wild for shpy to not be versioned. Tag some node as 1.0.0 and we can go from there

Support dash, ksh, and pdksh

shpy already supports ash and mksh, so this should be as simple as pulling the shell binaries into the Docker container and adding new Docker compose services and Travis CI matrices

Fails if nounset bash option set

If the nounset bash option is set, spies will fail due to checking of undefined variables.

Example:

#!/usr/bin/env bash

set -o nounset

testNoUnset() {
  createSpy some_cmd

  some_cmd
}

. ../shpy/shpy
. ../shpy/shpy-shunit2
. ./shunit2

Output:

testNoUnset
../shpy/shpy: line 153: _shpy_inited: unbound variable
ASSERT:unknown failure encountered running a test

Ran 1 test.

FAILED (failures=1)

Add multiple output sequences

Similar to the current ability to return a sequence of values with

createSpy -r 4 -r 3 -r 9 some_command

we should be able to pass in a sequence of outputs, which will be printed to stdout on successive calls to the mock, in the order they are passed.

For example:

createSpy -o "foo bar" -o "abc def" some_command
some_command 
# foo bar
some_command
# abc def
some_command
# abc def

Fix coverage reporting

This may be blocked by #14, since a shpy container would make it easy to control and debug our kcov environment. Looks like kcov isn't behaving properly and is spewing output to stdout when it should be in PS4 or something, which causes builds to fail with no reporting data

Better naming conventions for tests

Things to note:

  • Test names are a bit of a mess, they don't mentioned specifically what's under test
    • They should follow a conventional style like itShowsUsageWhenCreatingSpyWithoutArgs
  • t/ should be renamed to test/ for clarity, and to make it easier to click on GitHub honestly
  • Assert messages should specify what went wrong, not what was expected
    • "Result is true" isn't helpful when the result is actually false

Add unit testing example to README

Unit testing is still relatively new to the shell scripting world. The average shell programmer isn't going to know what unit testing is for and when you would use it, so it's even more unlikely that they'd know why you would want to use spies and stubs.

There needs to be a concise yet complete introduction to shell unit testing with spies and fakes that not only explains how to use the functions in shpy, but it would also explain:

  • why unit testing is useful
  • how you go about unit testing shell scripts
  • what problem spies and stubs solve
  • how to use spies effectively

I feel like I know what needs to be said, but at this point I still need to think of a programming problem that:

  • illustrates the relevant testing concepts
  • is a problem that most programmers can relate to and understand
  • is concise enough that we don't have to go into needless detail

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.