44
55import pytest
66
7- from splitfolders import fixed , ratio
7+ from splitfolders import fixed , kfold , ratio
88
99
1010def test_second_package ():
@@ -251,6 +251,95 @@ def test_split_fixed_oversample_prefix():
251251 assert a != b
252252
253253
254+ def test_split_ratio_symlink ():
255+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
256+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
257+
258+ shutil .rmtree (output_dir , ignore_errors = True )
259+
260+ ratio (input_dir , output_dir , move = "symlink" )
261+
262+ # ensure the number of pics is the same
263+ a = len (list (pathlib .Path (input_dir ).glob ("**/*.jpg" )))
264+ b = len (list (pathlib .Path (output_dir ).glob ("**/*.jpg" )))
265+ assert a == b
266+
267+ # ensure all output files are symlinks
268+ for f in pathlib .Path (output_dir ).rglob ("*.jpg" ):
269+ assert f .is_symlink ()
270+
271+
272+ def test_split_fixed_symlink ():
273+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
274+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
275+
276+ shutil .rmtree (output_dir , ignore_errors = True )
277+
278+ fixed (input_dir , output_dir , fixed = (2 , 2 ), move = "symlink" )
279+
280+ # ensure the number of pics is the same
281+ a = len (list (pathlib .Path (input_dir ).glob ("**/*.jpg" )))
282+ b = len (list (pathlib .Path (output_dir ).glob ("**/*.jpg" )))
283+ assert a == b
284+
285+ # ensure all output files are symlinks
286+ for f in pathlib .Path (output_dir ).rglob ("*.jpg" ):
287+ assert f .is_symlink ()
288+
289+
290+ def test_split_ratio_formats ():
291+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs_texts" )
292+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
293+
294+ shutil .rmtree (output_dir , ignore_errors = True )
295+
296+ ratio (input_dir , output_dir , formats = [".jpg" ])
297+
298+ # only jpg files should be in output
299+ jpg_count = len (list (pathlib .Path (output_dir ).glob ("**/*.jpg" )))
300+ txt_count = len (list (pathlib .Path (output_dir ).glob ("**/*.txt" )))
301+ assert jpg_count > 0
302+ assert txt_count == 0
303+
304+
305+ def test_split_fixed_formats ():
306+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs_texts" )
307+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
308+
309+ shutil .rmtree (output_dir , ignore_errors = True )
310+
311+ fixed (input_dir , output_dir , fixed = (1 , 1 ), formats = [".txt" ])
312+
313+ # only txt files should be in output
314+ jpg_count = len (list (pathlib .Path (output_dir ).glob ("**/*.jpg" )))
315+ txt_count = len (list (pathlib .Path (output_dir ).glob ("**/*.txt" )))
316+ assert txt_count > 0
317+ assert jpg_count == 0
318+
319+
320+ def test_split_ratio_formats_multiple ():
321+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs_texts" )
322+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
323+
324+ shutil .rmtree (output_dir , ignore_errors = True )
325+
326+ ratio (input_dir , output_dir , formats = [".jpg" , ".txt" ])
327+
328+ # both jpg and txt files should be in output
329+ jpg_count = len (list (pathlib .Path (output_dir ).glob ("**/*.jpg" )))
330+ txt_count = len (list (pathlib .Path (output_dir ).glob ("**/*.txt" )))
331+ assert jpg_count > 0
332+ assert txt_count > 0
333+
334+
335+ def test_invalid_formats ():
336+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
337+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
338+
339+ with pytest .raises (ValueError ):
340+ ratio (input_dir , output_dir , formats = ["jpg" ])
341+
342+
254343def test_split_ratio_prefix_error_1 ():
255344 input_dir = os .path .join (os .path .dirname (__file__ ), "imgs_texts_error_1" )
256345 output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
@@ -269,3 +358,93 @@ def test_split_ratio_prefix_error_2():
269358
270359 with pytest .raises (ValueError ):
271360 ratio (input_dir , output_dir , group_prefix = 2 )
361+
362+
363+ def test_kfold_basic ():
364+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
365+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
366+
367+ shutil .rmtree (output_dir , ignore_errors = True )
368+
369+ kfold (input_dir , output_dir , k = 5 , move = False )
370+
371+ # verify 5 fold directories created
372+ fold_dirs = sorted (pathlib .Path (output_dir ).iterdir ())
373+ assert len (fold_dirs ) == 5
374+
375+ input_count = len (list (pathlib .Path (input_dir ).glob ("**/*.jpg" )))
376+
377+ for fold_dir in fold_dirs :
378+ # each fold should have train/ and val/
379+ assert (fold_dir / "train" ).is_dir ()
380+ assert (fold_dir / "val" ).is_dir ()
381+
382+ # train + val should equal input count
383+ train_count = len (list ((fold_dir / "train" ).rglob ("*.jpg" )))
384+ val_count = len (list ((fold_dir / "val" ).rglob ("*.jpg" )))
385+ assert train_count + val_count == input_count
386+
387+ # no overlap between train and val
388+ train_files = {f .name for f in (fold_dir / "train" ).rglob ("*.jpg" )}
389+ val_files = {f .name for f in (fold_dir / "val" ).rglob ("*.jpg" )}
390+ assert train_files .isdisjoint (val_files )
391+
392+
393+ def test_kfold_3 ():
394+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
395+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
396+
397+ shutil .rmtree (output_dir , ignore_errors = True )
398+
399+ kfold (input_dir , output_dir , k = 3 , move = False )
400+
401+ fold_dirs = sorted (pathlib .Path (output_dir ).iterdir ())
402+ assert len (fold_dirs ) == 3
403+
404+
405+ def test_kfold_symlink ():
406+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
407+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
408+
409+ shutil .rmtree (output_dir , ignore_errors = True )
410+
411+ kfold (input_dir , output_dir , k = 3 )
412+
413+ # default is symlink
414+ for f in pathlib .Path (output_dir ).rglob ("*.jpg" ):
415+ assert f .is_symlink ()
416+
417+
418+ def test_kfold_copy ():
419+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
420+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
421+
422+ shutil .rmtree (output_dir , ignore_errors = True )
423+
424+ kfold (input_dir , output_dir , k = 3 , move = False )
425+
426+ # move=False means real copies, not symlinks
427+ for f in pathlib .Path (output_dir ).rglob ("*.jpg" ):
428+ assert not f .is_symlink ()
429+
430+
431+ def test_kfold_formats ():
432+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs_texts" )
433+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
434+
435+ shutil .rmtree (output_dir , ignore_errors = True )
436+
437+ kfold (input_dir , output_dir , k = 3 , move = False , formats = [".jpg" ])
438+
439+ jpg_count = len (list (pathlib .Path (output_dir ).rglob ("*.jpg" )))
440+ txt_count = len (list (pathlib .Path (output_dir ).rglob ("*.txt" )))
441+ assert jpg_count > 0
442+ assert txt_count == 0
443+
444+
445+ def test_kfold_invalid ():
446+ input_dir = os .path .join (os .path .dirname (__file__ ), "imgs" )
447+ output_dir = os .path .join (os .path .dirname (__file__ ), "output" )
448+
449+ with pytest .raises (ValueError ):
450+ kfold (input_dir , output_dir , k = 1 )
0 commit comments