{"id":23092301,"url":"https://github.com/sourcefrog/shellliketests","last_synced_at":"2026-02-05T08:32:14.696Z","repository":{"id":8973511,"uuid":"10716822","full_name":"sourcefrog/shellliketests","owner":"sourcefrog","description":"Test command-line programs from Python by giving example input and output","archived":false,"fork":false,"pushed_at":"2013-06-16T23:22:43.000Z","size":144,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-25T22:47:52.704Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sourcefrog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-06-16T06:49:36.000Z","updated_at":"2014-01-18T22:11:02.000Z","dependencies_parsed_at":"2022-09-18T15:13:49.718Z","dependency_job_id":null,"html_url":"https://github.com/sourcefrog/shellliketests","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sourcefrog/shellliketests","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcefrog%2Fshellliketests","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcefrog%2Fshellliketests/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcefrog%2Fshellliketests/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcefrog%2Fshellliketests/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sourcefrog","download_url":"https://codeload.github.com/sourcefrog/shellliketests/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcefrog%2Fshellliketests/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29117042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-16T21:32:04.604Z","updated_at":"2026-02-05T08:32:14.679Z","avatar_url":"https://github.com/sourcefrog.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"Shell-like tests\n================\n\n* Licence: GNU GPL v2+\n* Home page: https://github.com/sourcefrog/shelliketests\n* Maintainer: Martin Pool \u003cmbp@sourcefrog.net\u003e\n* Dependencies: Python 2.6..3.3 (nothing else)\n\n`shellliketests` allows users to write tests in a syntax very close to a\nshell session, using a restricted and limited set of commands that should\nbe enough to mimic most of the behaviours.  For example:\n\n```python\n    def test_echo(self):\n        run_script(self, \"\"\"\n            $ echo hello world\n            hello world\n            \"\"\")\n```\n\nFeatures and benefits:\n\n* Provides a concise way to run commands and check output.\n\n* Commands can either be really run as subprocesses, or selectively\n  intercepted and run in-process (eg by calling something like the `main`\n  routine of a Python program).  Running in process may be substantially\n  faster and can allow more precise control of the test environment.\n\n* Abstracts cross-platform differences: for example `rm` can be used\n  across Windows and Unix.\n\n* Sections of output can be ignored if they don't matter (like in Doctests.)\n\nShell-like tests don't cover every kind of test you should write, but they\ndo make one class of tests easier.\n\nA script is a set of commands, each command is composed of:\n\n* one mandatory command line,\n* one optional set of input lines to feed the command,\n* one optional set of output expected lines,\n* one optional set of error expected lines.\n\nInput, output and error lines can be specified in any order.\n\nExcept for the expected output, all lines start with a special\nstring (based on their origin when used under a Unix shell):\n\n* `$ ` for the command,\n* `\u003c` for input,\n* nothing for output,\n* `2\u003e` for errors,\n\nComments can be added anywhere, they start with '#' and end with\nthe line.\n\nThe execution stops as soon as an expected output or an expected error is not\nmatched.\n\nIf output occurs and no output is expected, the execution stops and the\ntest fails.  If unexpected output occurs on the standard error, then\nexecution stops and the test fails.\n\nIf an error occurs and no expected error is specified, the execution stops.\n\nAn error is defined by a returned status different from zero, not by the\npresence of text on the error stream.\n\nThe matching is done on a full string comparison basis unless `...` is used, in\nwhich case expected output/errors can be less precise.\n\nExamples\n--------\n\n(`bzr` here is just an example; there's nothing bzr-specific.)\n\nThe following will succeed only if `bzr add` outputs `adding file`:\n\n    $ bzr add file\n    adding file\n\nIf you want the command to succeed for any output, just use:\n\n    $ bzr add file\n    ...\n    2\u003e...\n\nThe following script will raise an error:\n\n    $ bzr not-a-command\n\nIf you want it to succeed, add expected error output matching what the\nprogram will produce for this argument:\n\n    $ bzr not-a-command\n    2\u003e bzr: ERROR: unknown command \"not-a-command\"\n\nYou can use ellipsis (...) to replace any piece of text you don't want to be\nmatched exactly, like in Doctest:\n\n    $ bzr branch not-a-branch\n    2\u003ebzr: ERROR: Not a branch...not-a-branch/\".\n\nThis can be used to ignore entire lines too:\n\n    $ cat\n    \u003cfirst line\n    \u003csecond line\n    \u003cthird line\n    # And here we explain that surprising fourth line\n    \u003cfourth line\n    \u003clast line\n    # Now we expect cat to write out what was written in:\n    first line\n    second line\n    third line\n    fourth line\n    last line\n\nYou can check the content of a file with `cat`:\n\n    $ cat file\n    expected content\n\nYou can also check the existence of a file with `cat`, which will fail if\nthe file does not exist:\n\n    $ cat file\n    ...\n\nThe actual use of ScriptRunner within a TestCase looks something like\nthis:\n\n```python\n    from shelliketests import run_script\n\n    def test_unshelve_keep(self):\n        # some setup here\n        run_script(self, '''\n            $ bzr add -q file\n            $ bzr shelve -q --all -m Foo\n            $ bzr shelve --list\n            1: Foo\n            $ bzr unshelve -q --keep\n            $ bzr shelve --list\n            1: Foo\n            $ cat file\n            contents of file\n            ''')\n```\n\nYou can also test commands that read user interaction:\n\n```python\n    def test_confirm_action(self):\n        \"\"\"You can write tests that demonstrate user confirmation\"\"\"\n        run_script(\"\"\"\n            $ bzr test-confirm\n            2\u003eReally do it? [y/n]: \n            \u003cyes\n            yes\n            \"\"\")\n```\n\nTo avoid having to specify `...` for all commands whose output is\nirrelevant, the `run_script()` method may be passed the keyword argument\n`null_output_matches_anything=True`.  For example:\n\n```python\n    def test_ignoring_null_output(self):\n        run_script(\"\"\"\n            $ bzr init\n            $ bzr ci -m 'first revision' --unchanged\n            $ bzr log --line\n            1: ...\n            \"\"\", null_output_matches_anything=True)\n```\n\nAuthors\n-------\n\nThis code is based on the `bzrlib.tests.script` module in\n[Bazaar](http://bazaar.canonical.com/), but updated to remove coupling to\nbzr and the bzr test suite.  This code was originally developed by\nCanonical Ltd and written by:\n\n* Vincent Ladieul\n* Martin Pool\n* Robert Collins\n* John Arbash Meinel\n* Martin gz\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsourcefrog%2Fshellliketests","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsourcefrog%2Fshellliketests","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsourcefrog%2Fshellliketests/lists"}