{"id":16444902,"url":"https://github.com/jaymon/testdata","last_synced_at":"2025-07-10T22:44:44.508Z","repository":{"id":8047179,"uuid":"9457942","full_name":"Jaymon/testdata","owner":"Jaymon","description":"Python module to make testing easier, it can generate random data like names and text, run commands, fetch urls, create files and directories, and more","archived":false,"fork":false,"pushed_at":"2025-01-30T23:38:06.000Z","size":852,"stargazers_count":10,"open_issues_count":28,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-11T10:50:26.920Z","etag":null,"topics":["ascii","python","test","test-coverage","test-driven-development","testdata","testing","testing-tools","unicode"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jaymon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-15T20:49:59.000Z","updated_at":"2025-01-30T23:38:09.000Z","dependencies_parsed_at":"2024-08-17T10:15:53.410Z","dependency_job_id":null,"html_url":"https://github.com/Jaymon/testdata","commit_stats":{"total_commits":182,"total_committers":1,"mean_commits":182.0,"dds":0.0,"last_synced_commit":"42158d960dc298e2711e0d0f6b68f2f2659e5afd"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Ftestdata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Ftestdata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Ftestdata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jaymon%2Ftestdata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jaymon","download_url":"https://codeload.github.com/Jaymon/testdata/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243725026,"owners_count":20337660,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["ascii","python","test","test-coverage","test-driven-development","testdata","testing","testing-tools","unicode"],"created_at":"2024-10-11T09:42:32.385Z","updated_at":"2025-03-15T11:33:07.816Z","avatar_url":"https://github.com/Jaymon.png","language":"Python","readme":"# Testdata\n\nGenerate Random Test Data.\n\nThese are just a bunch of handy functions designed to make it easier to test your code.\n\nTo use testdata in your tests, just import it into your testing module:\n\n    import testdata\n\nTo install, use Pip:\n\n    pip install testdata\n\nOr, with Pip using Github:\n\n    pip install --upgrade \"git+https://github.com/Jaymon/testdata#egg=testdata\"\n\n\n## Using Testdata\n\nThe easiest way to use testdata is to use `testdata.TestCase` while writing your [unittest](https://docs.python.org/3/library/unittest.html) tests:\n\n```python\nfrom testdata import TestCase\nimport testdata\n\nclass CustomTest(TestCase):\n    def test_foo(self):\n        # use testdata methods by magic:\n        print(self.get_int())\n        \n        # or, be more explicit and use the .data attribute:\n        print(self.data.get_int())\n        \n        # finally, you can call anything at the module level also:\n        print(testdata.get_int())\n```\n\nTo use testdata with other testing frameworks, or outside of tests, just import the module and use it:\n\n```python\nimport testdata\n\ntestdata.get_int()\n```\n\n\n## Extending Testdata\n\nThe testdata module has a ton of helpful methods, and you can also easily add your own custom methods by extending `testdata.TestData`:\n\n```python\nfrom testdata import TestData, NumberData\n\nclass CustomData(TestData):\n    \"\"\"Bespoke methods\"\"\"\n    def foobar(self):\n        return \"foobar\"\n\nclass CustomNumberData(NumberData):\n    \"\"\"overrides default get_int functionality\"\"\"\n    def get_int(self, *args, **kwargs):\n        return 1\n\ntestdata.foobar() # foobar\ntestdata.get_int() # 1\n```\n\nThe only catch to adding/overriding testdata methods is you have to make sure your custom `TestData` child classes are imported before you can call them since testdata makes use of [__init_subclass__](https://peps.python.org/pep-0487/) to add `TestData` classes to the resolver.\n\n\n## Functionality\n\nThis is an overview of some of the functions and classes found in the Testdata module, there are other functions (like `get_birthday`) that aren't listed here, for the complete list just look at the [source](https://github.com/Jaymon/testdata/tree/master/testdata). Any methods on any child class that extends `testdata.base.TestData` will be available at `testdata.\u003cMETHOD-NAME\u003e`.\n\n\n### patch\n\n\n#### Patching modules and classes\n\n```python\npatch(mod, **patches)\n```\n\nPatches a module, instance, or class with the given patches.\n\nSuppose you had a module like this:\n\n```python\n# module foo.bar\n\ndef boom():\n    return 1\n\nclass FooPatch(object):\n    @classmethod\n    def bam(cls): return boom()\n```\n\nNow you can easily patch it for testing:\n\n```python\ndef mock_boom():\n    return 2\n\nfoo_bar = testdata.patch('foo.bar', boom=mock_boom)\nprint foo_bar.FooPatch.bam() # 2\n\n# but you can also just pass in objects or modules\n\nfrom foo.bar import FooPatch\nFooPatch = testdata.patch(FooPatch, boom=mock_boom)\nprint FooPatch.bam() # 2\n\nfrom foo import bar\nbar = testdata.patch(bar, boom=mock_boom)\nprint bar.FooPatch.bam() # 2\n```\n\n\n#### Patching class instances\n\nYou can also patch a specific instance\n\nSuppose you had a module like this:\n\n```python\n# module foo.bar\n\nclass Foo(object):\n    def boom(self): return 1\n```\n\nNow you can easily patch it for testing:\n\n```python\ndef mock_boom():\n    return 2\n\nfoo = Foo()\nfoo_patched = testdata.patch(foo, boom=mock_boom)\nprint foo_patched.boom() # 2\n\n# be aware though, the original instance was modified, foo_patched == foo\nprint foo.boom() # 2\n```\n\n\n-------------------------------------------------------------------------------\n\n### run\n\nRun a command on the command line\n\n\n```python\nr = testdata.run(\"echo 1\")\nprint(r) # 1\n```\n\n\n-------------------------------------------------------------------------------\n\n### fetch\n\nRequest a url\n\n\n```python\nr = testdata.fetch(\"http://example.com\")\nprint(r.code) # 200\nprint(r.body) # the html body of example.com\n```\n\n\n-------------------------------------------------------------------------------\n\n### capture\n\nOutput buffering, handy when you want to make sure logging or print statements are doing what you think they should be doing.\n\n```python\nwith testdata.capture() as c:\n    print(\"foo\")\nif \"foo\" in c:\n    print(\"foo was captured\")\n```\n\n\n-------------------------------------------------------------------------------\n\n### Threading\n\nA wrapper around python's builtin `threading.Thread` class that bubbles errors up to the main thread because, by default, python's threading classes suppress errors, this makes it annoying when using threads for testing. __NOTE__ - This is buggier than I would like.\n\n```python\ndef run():\n    raise ValueError(\"join_2\")\n\nthread = testdata.Thread(target=run)\nthread.start()\nprint(thread.exception)\n```\n\n\n-------------------------------------------------------------------------------\n\n### File Server\n\nSometimes you need to test fetching remote files\n\n\n```python\nimport requests\n\nserver = testdata.create_fileserver({\n    \"foo.txt\": [\"foo\"],\n    \"bar.txt\": [\"bar\"],\n})\n\nwith server: # the with handles starting and stopping the server\n    res = testdata.fetch(server.url(\"foo.txt\"))\n    print(res.body) # foo\n```\n\n\n-------------------------------------------------------------------------------\n\n### environment\n\nChange your environment with this context manager, if you don't pass in an object as the first value it will default to `os.environ`\n\n```python\nwith testdata.enviroment(FOO=1):\n    print(os.environ[\"FOO\"]) # 1\nprint(os.environ[\"FOO\"]) # raises KeyError\n\n# you can also modify objects:\n\nd = {}\n\nwith testdata.enviroment(d, FOO=1):\n    print(d[\"FOO\"]) # 1\nprint(d[\"FOO\"]) # raises KeyError\n```\n\n\n-------------------------------------------------------------------------------\n\n### create_dir\n\n```python\ncreate_dir(path=\"\", tmpdir=\"\")\n```\n\ncreate a directory hierarchy\n\n```python\nbase_dir = \"/tmp\"\nd = testdata.create_dir(\"/foo/bar\", base_dir)\nprint d # /tmp/foo/bar\n```\n\n\n### create_dirs\n\n```python\ncreate_dirs(dirs, tmpdir=\"\")\n```\n\nCreate a bunch of files and folders\n\n```python\ntestdata.create_dirs({\n  \"foo\": {\n    \"bar\": {\n      \"che.txt\": [\"line 1\", \"line 2\"],\n    }\n  }\n})\n```\n\n-------------------------------------------------------------------------------\n\n### create_file\n\n```python\ncreate_file(data=\"\", path=\"\", tmpdir=\"\", encoding=\"\")\n```\n\ncreate a file with contents\n\n```python\nbase_dir = \"/tmp\"\nf = testdata.create_file(path=\"/foo/bar.txt\", data=\"The file contents\", tmpdir=base_dir)\nprint f # /tmp/foo/bar.txt\n```\n\n-------------------------------------------------------------------------------\n\n### create_files\n\n```python\ncreate_files(file_dict, tmpdir=\"\")\n```\n\nCreate a whole bunch of files, the `file_dict` key is the filename, the value is the contents of the file.\nThe `file_dict` is very similar to the `create_modules` param `module_dict`\n\n```python\nfile_dict = {\n    \"foo/bar.txt\": \"the foo file contents\",\n    \"baz.txt\": \"the baz file contents\",\n}\nf = testdata.create_files(file_dict)\n```\n\n-------------------------------------------------------------------------------\n\n### get_file\n\n```python\nget_file(path=\"\", tmpdir=\"\")\n```\n\nThis will return a `Filepath` instance that you can manipulate but unlike `create_file` it won't actually create the file, just give you a path to a file that could be created.\n\n\n-------------------------------------------------------------------------------\n\n### create_module\n\n```python\ncreate_module(data=\"\", modpath=\"\", tmpdir=\"\", make_importable=True)\n```\n\ncreate a module with python contents that can be imported\n\n```python\nbase_dir = \"/tmp\"\nf = testdata.create_module(modpath=\"foo.bar\", data=\"class Che(object): pass\", tmpdir=base_dir)\nprint f # /tmp/foo/bar.py\n```\n\n-------------------------------------------------------------------------------\n\n### create_modules\n\n```python\ncreate_modules(module_dict, tmpdir=\"\", make_importable=True)\n```\n\ncreate a whole bunch of modules at once\n\n```python\nf = testdata.create_modules(\n  {\n    \"foo.bar\": \"class Che(object): pass\",\n    \"foo.bar.baz\": \"class Boom(object): pass\",\n    \"foo.che\": \"class Bam(object): pass\",\n  }\n)\n```\n\n-------------------------------------------------------------------------------\n\n### get_ascii\n\n```python\nget_ascii(str_size=0)\n```\n\nreturn a string of ascii characters\n\n    \u003e\u003e\u003e testdata.get_ascii()\n    u'IFUKzVAauqgyRY6OV'\n\n\n-------------------------------------------------------------------------------\n\n### get_md5\n\n```python\nget_md5(val=\"\")\n```\n\nreturn an md5 hash of val (if passed in) or a random val if val is empty\n\n    \u003e\u003e\u003e testdata.get_md5()\n    'e165765400b30772f1d9b3975ce77320'\n\n\n-------------------------------------------------------------------------------\n\n### get_hash\n\n```python\nget_hash(str_size=32)\n```\n\nreturn a random hash\n\n    \u003e\u003e\u003e testdata.get_hash()\n    \"jYw3HseUl8GLoMc8QejLYFogC2lUYoUs\"\n\n\n-------------------------------------------------------------------------------\n\n### get_bool\n\n```python\nget_bool()\n```\n\nreturn a boolean (either **True** or **False**)\n\n    \u003e\u003e\u003e testdata.get_bool()\n    False\n    \u003e\u003e\u003e testdata.get_bool()\n    True\n\n-------------------------------------------------------------------------------\n### get_float\n\n```python\nget_float(min_size=None, max_size=None)\n```\n\nreturn a floating point number between `min_size` and `max_size`.\n\n    \u003e\u003e\u003e testdata.get_float()\n    2.932229899095845e+307\n\n-------------------------------------------------------------------------------\n\n### get_int\n\n```python\nget_int(min_size=1, max_size=sys.maxsize)\n```\n\nreturn an integer between `min_size` and `max_size`.\n\n    \u003e\u003e\u003e testdata.get_int()\n    3820706953806377295\n\n-------------------------------------------------------------------------------\n\n### get_name\n\n```python\nget_name(name_count=2, as_str=True)\n```\n\nreturns a random name that can be outside the ascii range (eg, name can be unicode)\n\n    \u003e\u003e\u003e testdata.get_name()\n    u'jamel clarke-cabrera'\n\n-------------------------------------------------------------------------------\n\n### get_email\n\n```python\nget_email(name=u'')\n```\n\nreturns a random email address in the ascii range.\n\n    \u003e\u003e\u003e testdata.get_email()\n    u'shelley@gmail.com'\n\n-------------------------------------------------------------------------------\n\n### get_str\n\n```python\nget_str(str_size=0, chars=None)\n```\n\nreturn random characters, which can be unicode.\n\n    \u003e\u003e\u003e testdata.get_str()\n    \"q\\x0bwZ\\u79755\\ud077\\u027aYm\\ud0d8JK\\x07\\U0010df418tx\\x16\"\n\n-------------------------------------------------------------------------------\n\n### get_url\n\n```python\nget_url()\n```\n\nreturn a random url.\n\n    \u003e\u003e\u003e testdata.get_url()\n    u'https://sK6rxrCa626TkQddTyf.com'\n\n-------------------------------------------------------------------------------\n\n### get_words\n\n```python\nget_words(word_count=0, as_str=True)\n```\n\nreturn a random amount of words, which can be unicode.\n\n    \u003e\u003e\u003e testdata.get_words()\n    \"\\u043f\\u043e\\u043d\\u044f\\u0442\\u044c \\u043c\\u043e\\u0436\\u043d\\u043e felis, habitasse ultrices Nam \\u0436\\u0435\\u043d\\u0430\"\n\n-------------------------------------------------------------------------------\n\n### get_past_datetime\n\n```python\nget_past_datetime([now])\n```\n\nreturn a datetime guaranteed to be in the past from `now`\n\n    \u003e\u003e\u003e testdata.get_past_datetime()\n    datetime.datetime(2000, 4, 2, 13, 40, 11, 133351)\n\n-------------------------------------------------------------------------------\n\n### get_future_datetime\n\n```python\nget_future_datetime([now])\n```\n\nreturn a datetime guaranteed to be in the future from `now`\n\n    \u003e\u003e\u003e testdata.get_future_datetime()\n    datetime.datetime(2017, 8, 3, 15, 54, 58, 670249)\n\n-------------------------------------------------------------------------------\n\n### get_between_datetime\n\n```python\nget_between_datetime(start[, stop])\n```\n\nreturn a datetime guaranteed to be in the future from `start` and in the past from `stop`\n\n    \u003e\u003e\u003e start = datetime.datetime.utcnow() - datetime.timedelta(days=100)\n    \u003e\u003e\u003e testdata.get_between_datetime(start)\n    datetime.datetime(2017, 8, 3, 15, 54, 58, 670249)\n\n-------------------------------------------------------------------------------\n\n## Development\n\n### Testing\n\nTesting on MacOS:\n\n    $ python -m unittest testdata_test\n\n\n### Dependencies\n\nDevelopment needs [datatypes](https://github.com/Jaymon/datatypes) on the path. This is kind of a strange thing because datatypes depends on `testdata` for testing. Making `datatypes` available to `testdata` for development should be as easy as:\n\n```\nexport PYTHONPATH=$PYTHONPATH:/path/to/dir/containing/datatypes\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaymon%2Ftestdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaymon%2Ftestdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaymon%2Ftestdata/lists"}