Git Product home page Git Product logo

beancount-hypothesis's Introduction

beancount-hypothesis

A package which provides hypothesis strategies for generating beancount types.

Usage

Strategies are provided for all of the core types present in beancount. The below example generates a random list of directives:

import beancount_hypothesis as h
from hypothesis import given, strategies as s

@given(
    s.recursive(
        h.balance()
        | h.close()
        | h.commodity()
        | h.custom()
        | h.document()
        | h.event()
        | h.note()
        | h.open()
        | h.query()
        | h.pad()
        | h.price()
        | h.transaction(),
        s.lists,
        max_leaves=5,
    )
)

Most of the types have restrictions placed on them with the following philosophy:

  • The value shouldn't break the beancount package
  • The value should be somewhat authentic (i.e. resemble user data)

Note that the input generated from the strategies is not intended to be passed to any beancount functions. In other words, passing the above example to the loader will result in undefined behavior as it doesn't follow any sensible rules.

Testing

tox

While testing a package meant for tests seems slightly redundant, there are some custom compositions present that benefit from testing. In most cases the tests just assert that generating data doesn't raise any exceptions (i.e. break beancount in some way).

Contributing

Check out the issues for items needing attention or submit your own and then:

  1. Fork the repo
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

beancount-hypothesis's People

Contributors

jmgilman avatar

Watchers

 avatar  avatar  avatar

beancount-hypothesis's Issues

Avoid using `random` module inside Hypothesis strategies

Hey there! I was looking through packages that use Hypothesis, and noticed something pretty weird:

@strategies.composite
def account_name(_) -> str:
"""Generates a random account name.
Returns:
A random account name.
"""
ag = AccountGenerator(min_nodes=1, max_nodes=1, min_leaves=3, max_leaves=3)
return ag.generate()[0]

@s.composite
def word(_) -> str:
"""Generates a random word.
Returns:
A new strategy
"""
rw = RandomWords()
return rw.random_word()

These strategies don't actually use Hypothesis to generate data! Instead, you're using the global random module, which Hypothesis seeds before every example to avoid flakiness. That's really really not intended to be used like this though - you'll be "generating" more or less the same example each time, and if it does fail shrinking won't work very well.


On a lighter note, you also have one that just doesn't need to be a composite strategy: instead of

@s.composite
def inventory(draw: s.DrawFn) -> inv.Inventory:
"""Generates a random Inventory of Positions.
Returns:
A new search strategy.
"""
positions = draw(s.lists(position(), max_size=3))
return inv.Inventory(positions)

you could return st.builds(inv.Inventory, s.lists(position(), max_size=3))

Random words are individually fetched from a web API ?!?!

It turns out that the random_word package fetches each word individually from https://developer.wordnik.com/ - this is totally unsuitable for a testing library, since it makes tests flaky and needlessly dependent on external infrastructure.

rw = RandomWords()
return rw.random_word()

See here and here for the upstream implementation.

Instead, you should use Hypothesis (not random - see #1) to choose words from a list which is statically defined in beancount-hypothesis, whether in Python or a data file (Hypothesis does this for top-level domains, for example). In fact I'd even recommend using Hypothesis to generate strings directly, instead of using real words - it looks less like production data, but is far more likely to find bugs.

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.