Skip to main content

ExploTest

Project description

ExploTest

ExploTest is a dynamic test extractor for iPython. It requires python vesion >= 3.10. To install, run pip install explotest.

Options

ExploTest generates by default a concise version of tests where elements in lists, dicts and tuples are asserted on a single line using the default python list/dict/tuple comparison whenever possible. If this behaviour is not desired, -v/--verbose can be toggled to generate assertion on every item individually. The test file name as well as the test resource folder name can also be modified by -f/--filename and -d/--dest, respectively.

Running ExploTest

ExploTest can be either run as an iPython plugin (mostly function-level exploratory runs) or as a Python command line tool (system-level exploratory runs).

To run as an iPython plugin:

Within an ipython session, run %reload_ext explotest and %transform_tests {options} (see above), and a test function will be produced.

To run as a command line tool

If the original invocation is python ./{in_file_name} {args_to_in_file_name}, run

$ python -m explotest ./{in_file_name} {options} -- {args_to_in_file_name}

This will create a separate ipython shell, run the entire content in ./{in_file_name} with the sys.args set to {args_to_in_file_name}, and a test function will be produced.

Some assumptions on the extractor and how to fix your code:

  1. Generally, no global states. As the extractor essentially runs your input again, for any sequence of inputs, it is assumed that the result running the sequence twice will be the same. This means that global states that may change during
    testing is not testable. This also means singleton patterns are more or less untestable. Pass the mechanism in as a class instead.

    To fix:

    Before:

    node_id = 0
    
    def get_new_id() -> int:
        global node_id
        node_id += 1
        return node_id
    
    
    class Foo:
        def __init__(self):
            self.node_id = get_new_id()
    
    
    if __name__ == "__main__":   # When testing
        assert Foo().node_id == 1
    

    After:

    class IDGenerator:
        def __init__(self):
            self.node_id = 0
            
            
        def get_next_id(self) -> int:
            self.node_id += 1
            return self.node_id
    
    
    class Foo:
        def __init__(self, id_gen: IDGenerator):
            self.node_id = id_gen.get_next_id()
    
    if __name__ == "__main__":  # When testing
        id_generator = IDGenerator()
        assert Foo(id_generator).node_id == 1
    

    or

    class IDGenerator:
        def __init__(self):
            self.node_id = 0
    
    
        def get_new_id(self) -> int:
            self.node_id += 1
            return self.node_id
    
    id_generator: IDGenerator = None
    
    def get_next_id():
        if id_generator is None:
            raise Exception()  # Can also return some default value
        return id_generator.get_new_id()
    
    def set_id_generator(id_gen: IDGenerator):
        global id_generator
        id_generator = id_gen
        
    class Foo:
        def __init__(self):
            self.node_id = get_next_id()
            
    if __name__ == "__main__":  # When testing
        set_id_generator(IDGenerator())
        assert Foo().node_id == 1
    
  2. (If using the carver):

    • A single point of return, situated at the bottom of the file
    • The state is not changed after the print
    • A returned value (if tuples) is a subset of exploratory print expression
    • The test generated is not super robust; specifically the test generated might not cover the entire list if the iterator loops through all the items (the index isn't retrievable)
    • Either the function is at the top level, or it is directly in some top level class (i. e. this must be directly retrievable at the top level)
    • Zero support for anonymous functions. Why would you want to test that?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

explotest-0.1.6.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ExploTest-0.1.6-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file explotest-0.1.6.tar.gz.

File metadata

  • Download URL: explotest-0.1.6.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for explotest-0.1.6.tar.gz
Algorithm Hash digest
SHA256 f1035cc32819d3f6f69e68d0980becae10a60b156a702f493124b7d10a09a7e2
MD5 738ae31babb35e1b8bb1c103017543b5
BLAKE2b-256 f941e81d0f2928d4629550bf06afad89a304a0e644b20faea6b1e75e98805b12

See more details on using hashes here.

File details

Details for the file ExploTest-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: ExploTest-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for ExploTest-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 3ea488e27b3d2e57e1819a85b782383c0c696df2fac9f9da632b651846291c43
MD5 1d5ebeefd72f2c081bd9a2fc7546d372
BLAKE2b-256 ded6acbaea52280706029f89311ef21bd5113e610d656e374a0179279926e079

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page