0

I want to add tests using the Hypothesis library (already use in the software for testing). For these tests, I have to use a set of txt files contained in a folder. I need to randomly choose one of these files each time I run my tests. How to do that using Hypothesis?

edit Here basically how it would look like, to comply the templates of already existing tests.

@given(doc=)
def mytest(doc):

    # assert some stuff according to doc
    assert some_stuff
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
David N
  • 509
  • 4
  • 12

1 Answers1

1

Static case

If files list is assumed to be "frozen" (no files will be deleted/added) then we can use os.listdir + hypohtesis.strategies.sampled_from like

import os

from hypothesis import strategies

directory_path = 'path/to/directory/with/txt/files'
txt_files_names = strategies.sampled_from(sorted(os.listdir(directory_path)))

or if we need full paths

from functools import partial
...
txt_files_paths = (strategies.sampled_from(sorted(os.listdir(directory_path)))
                   .map(partial(os.path.join, directory_path)))

or if the directory may have files of different extensions and we need only .txt ones we can use glob.glob

import glob
...
txt_files_paths = strategies.sampled_from(sorted(glob.glob(os.path.join(directory_path, '*.txt'))))

Dynamic case

If directory contents may change and we want to make directory scan on each data generation attempt it can be done like

dynamic_txt_files_names = (strategies.builds(os.listdir,
                                             strategies.just(directory_path))
                           .map(sorted)
                           .flatmap(strategies.sampled_from))

or with full paths

dynamic_txt_files_paths = (strategies.builds(os.listdir,
                                             strategies.just(directory_path))
                           .map(sorted)
                           .flatmap(strategies.sampled_from)
                           .map(partial(os.path.join, directory_path)))

or with glob.glob

dynamic_txt_files_paths = (strategies.builds(glob.glob,
                                             strategies.just(os.path.join(
                                                     directory_path,
                                                     '*.txt')))
                           .map(sorted)
                           .flatmap(strategies.sampled_from))

Edit

Azat Ibrakov
  • 9,998
  • 9
  • 38
  • 50
  • 1
    You should put a `.map(sorted)` before the flatmap to ensure that examples are reproducible - not all operating systems or file systems guarantee stable iteration order, and that would break replay. – Zac Hatfield-Dodds Feb 18 '20 at 11:09
  • 1
    the `sorted` specifically needs to be *before* `sampled_from` - as written you're not stabilising iteration order, you're converting a string to a sorted list of characters! – Zac Hatfield-Dodds Feb 22 '20 at 03:50
  • @ZacHatfield-Dodds: you are right, my mistake, tested only "static" case, should be fixed now – Azat Ibrakov Feb 22 '20 at 04:21