0
# File System Matchers
1
2
JVM file system operations including existence checks, permissions validation, content verification, size comparisons, and directory structure analysis for comprehensive file-based testing.
3
4
## Capabilities
5
6
### Existence and Type Validation
7
8
Matchers for validating file and directory existence and type classification.
9
10
```kotlin { .api }
11
/**
12
* Assert that file or directory exists on the file system
13
* @return The original File for chaining
14
*/
15
fun File.shouldExist(): File
16
17
/**
18
* Assert that file or directory does not exist
19
* @return The original File for chaining
20
*/
21
fun File.shouldNotExist(): File
22
23
/**
24
* Assert that path represents a directory
25
* @return The original File for chaining
26
*/
27
fun File.shouldBeADirectory(): File
28
29
/**
30
* Assert that path does not represent a directory
31
* @return The original File for chaining
32
*/
33
fun File.shouldNotBeADirectory(): File
34
35
/**
36
* Assert that path represents a regular file
37
* @return The original File for chaining
38
*/
39
fun File.shouldBeAFile(): File
40
41
/**
42
* Assert that path does not represent a regular file
43
* @return The original File for chaining
44
*/
45
fun File.shouldNotBeAFile(): File
46
47
/**
48
* Create matcher for existence validation
49
* @return Matcher that passes when file exists
50
*/
51
fun exist(): Matcher<File>
52
53
/**
54
* Create matcher for directory type validation
55
* @return Matcher that passes when path is a directory
56
*/
57
fun aDirectory(): Matcher<File>
58
59
/**
60
* Create matcher for file type validation
61
* @return Matcher that passes when path is a regular file
62
*/
63
fun aFile(): Matcher<File>
64
```
65
66
**Usage Examples:**
67
68
```kotlin
69
import io.kotest.matchers.file.*
70
import java.io.File
71
72
val configFile = File("/etc/config.txt")
73
val dataDirectory = File("/var/data")
74
val tempFile = File.createTempFile("test", ".tmp")
75
76
// Existence validation
77
configFile.shouldExist()
78
tempFile.shouldExist()
79
80
// Type validation
81
dataDirectory.shouldBeADirectory()
82
configFile.shouldBeAFile()
83
84
// Using matcher syntax
85
configFile should exist()
86
dataDirectory should aDirectory()
87
tempFile should aFile()
88
```
89
90
### Content and Emptiness
91
92
Matchers for validating file content, size, and emptiness states.
93
94
```kotlin { .api }
95
/**
96
* Assert that file is empty (size == 0 bytes)
97
* @return The original File for chaining
98
*/
99
fun File.shouldBeEmpty(): File
100
101
/**
102
* Assert that file is not empty (size > 0 bytes)
103
* @return The original File for chaining
104
*/
105
fun File.shouldNotBeEmpty(): File
106
107
/**
108
* Assert that directory is empty (contains no files or subdirectories)
109
* @return The original File for chaining
110
*/
111
fun File.shouldBeEmptyDirectory(): File
112
113
/**
114
* Assert that directory is not empty
115
* @return The original File for chaining
116
*/
117
fun File.shouldNotBeEmptyDirectory(): File
118
119
/**
120
* Assert that directory contains exactly specified number of files
121
* @param n Expected number of files in directory
122
* @return The original File for chaining
123
*/
124
infix fun File.shouldContainNFiles(n: Int): File
125
126
/**
127
* Assert that directory does not contain specified number of files
128
* @param n Number of files that should not match
129
* @return The original File for chaining
130
*/
131
infix fun File.shouldNotContainNFiles(n: Int): File
132
133
/**
134
* Assert that directory contains specified file by name
135
* @param name Name of file that should be present
136
* @return The original File for chaining
137
*/
138
infix fun File.shouldContainFile(name: String): File
139
140
/**
141
* Assert that directory does not contain specified file by name
142
* @param name Name of file that should not be present
143
* @return The original File for chaining
144
*/
145
infix fun File.shouldNotContainFile(name: String): File
146
147
/**
148
* Create matcher for empty file validation
149
* @return Matcher that passes for empty files
150
*/
151
fun beEmpty(): Matcher<File>
152
153
/**
154
* Create matcher for empty directory validation
155
* @return Matcher that passes for empty directories
156
*/
157
fun beEmptyDirectory(): Matcher<File>
158
159
/**
160
* Create matcher for directory file count validation
161
* @param n Expected number of files
162
* @return Matcher that passes when directory contains exactly n files
163
*/
164
fun containNFiles(n: Int): Matcher<File>
165
166
/**
167
* Create matcher for file presence in directory
168
* @param name Name of file to check for
169
* @return Matcher that passes when directory contains the named file
170
*/
171
fun containFile(name: String): Matcher<File>
172
```
173
174
**Usage Examples:**
175
176
```kotlin
177
import io.kotest.matchers.file.*
178
import java.io.File
179
180
val emptyFile = File("empty.txt").apply { writeText("") }
181
val dataDir = File("data/")
182
val configDir = File("config/")
183
184
// Emptiness validation
185
emptyFile.shouldBeEmpty()
186
dataDir.shouldNotBeEmptyDirectory()
187
188
// Directory content validation
189
configDir shouldContainNFiles 3
190
configDir shouldContainFile "settings.json"
191
192
// Using matcher syntax
193
emptyFile should beEmpty()
194
dataDir should containFile("users.db")
195
```
196
197
### Size and Comparison
198
199
Matchers for file size validation and comparative operations.
200
201
```kotlin { .api }
202
/**
203
* Assert that file has exactly specified size in bytes
204
* @param size Expected file size in bytes
205
* @return The original File for chaining
206
*/
207
infix fun File.shouldHaveFileSize(size: Long): File
208
209
/**
210
* Assert that file does not have specified size
211
* @param size Size in bytes that should not match
212
* @return The original File for chaining
213
*/
214
infix fun File.shouldNotHaveFileSize(size: Long): File
215
216
/**
217
* Assert that file is smaller than another file
218
* @param other File to compare against
219
* @return The original File for chaining
220
*/
221
infix fun File.shouldBeSmaller(other: File): File
222
223
/**
224
* Assert that file is not smaller than another file
225
* @param other File to compare against
226
* @return The original File for chaining
227
*/
228
infix fun File.shouldNotBeSmaller(other: File): File
229
230
/**
231
* Assert that file is larger than another file
232
* @param other File to compare against
233
* @return The original File for chaining
234
*/
235
infix fun File.shouldBeLarger(other: File): File
236
237
/**
238
* Assert that file is not larger than another file
239
* @param other File to compare against
240
* @return The original File for chaining
241
*/
242
infix fun File.shouldNotBeLarger(other: File): File
243
244
/**
245
* Create matcher for exact file size validation
246
* @param size Expected size in bytes
247
* @return Matcher that passes for files of exact size
248
*/
249
fun haveFileSize(size: Long): Matcher<File>
250
251
/**
252
* Create matcher for file size comparison (smaller)
253
* @param other File to compare against
254
* @return Matcher that passes when file is smaller than other
255
*/
256
fun beSmaller(other: File): Matcher<File>
257
258
/**
259
* Create matcher for file size comparison (larger)
260
* @param other File to compare against
261
* @return Matcher that passes when file is larger than other
262
*/
263
fun beLarger(other: File): Matcher<File>
264
```
265
266
### Permissions and Properties
267
268
Matchers for file permissions, attributes, and system properties.
269
270
```kotlin { .api }
271
/**
272
* Assert that file is readable by current process
273
* @return The original File for chaining
274
*/
275
fun File.shouldBeReadable(): File
276
277
/**
278
* Assert that file is not readable
279
* @return The original File for chaining
280
*/
281
fun File.shouldNotBeReadable(): File
282
283
/**
284
* Assert that file is writable by current process
285
* @return The original File for chaining
286
*/
287
fun File.shouldBeWriteable(): File
288
289
/**
290
* Assert that file is not writable
291
* @return The original File for chaining
292
*/
293
fun File.shouldNotBeWriteable(): File
294
295
/**
296
* Assert that file is executable by current process
297
* @return The original File for chaining
298
*/
299
fun File.shouldBeExecutable(): File
300
301
/**
302
* Assert that file is not executable
303
* @return The original File for chaining
304
*/
305
fun File.shouldNotBeExecutable(): File
306
307
/**
308
* Assert that file is hidden (system attribute)
309
* @return The original File for chaining
310
*/
311
fun File.shouldBeHidden(): File
312
313
/**
314
* Assert that file is not hidden
315
* @return The original File for chaining
316
*/
317
fun File.shouldNotBeHidden(): File
318
319
/**
320
* Assert that path is absolute (not relative)
321
* @return The original File for chaining
322
*/
323
fun File.shouldBeAbsolute(): File
324
325
/**
326
* Assert that path is not absolute (is relative)
327
* @return The original File for chaining
328
*/
329
fun File.shouldNotBeAbsolute(): File
330
331
/**
332
* Assert that path is relative (not absolute)
333
* @return The original File for chaining
334
*/
335
fun File.shouldBeRelative(): File
336
337
/**
338
* Assert that path is not relative (is absolute)
339
* @return The original File for chaining
340
*/
341
fun File.shouldNotBeRelative(): File
342
343
/**
344
* Create matcher for readable permission validation
345
* @return Matcher that passes for readable files
346
*/
347
fun beReadable(): Matcher<File>
348
349
/**
350
* Create matcher for writable permission validation
351
* @return Matcher that passes for writable files
352
*/
353
fun beWriteable(): Matcher<File>
354
355
/**
356
* Create matcher for executable permission validation
357
* @return Matcher that passes for executable files
358
*/
359
fun beExecutable(): Matcher<File>
360
361
/**
362
* Create matcher for hidden attribute validation
363
* @return Matcher that passes for hidden files
364
*/
365
fun beHidden(): Matcher<File>
366
367
/**
368
* Create matcher for absolute path validation
369
* @return Matcher that passes for absolute paths
370
*/
371
fun beAbsolute(): Matcher<File>
372
373
/**
374
* Create matcher for relative path validation
375
* @return Matcher that passes for relative paths
376
*/
377
fun beRelative(): Matcher<File>
378
```
379
380
**Usage Examples:**
381
382
```kotlin
383
import io.kotest.matchers.file.*
384
import java.io.File
385
386
val executableScript = File("/usr/bin/script.sh")
387
val configFile = File("config/app.properties")
388
val logFile = File("/var/log/app.log")
389
390
// Permission validation
391
executableScript.shouldBeReadable()
392
executableScript.shouldBeExecutable()
393
logFile.shouldBeWriteable()
394
395
// Path type validation
396
executableScript.shouldBeAbsolute()
397
configFile.shouldBeRelative()
398
399
// Size comparison
400
val smallFile = File("small.txt")
401
val largeFile = File("large.txt")
402
smallFile shouldBeSmaller largeFile
403
largeFile shouldHaveFileSize 1024L
404
405
// Using matcher syntax
406
executableScript should beExecutable()
407
configFile should beRelative()
408
```
409
410
### Path Type and Links
411
412
Advanced matchers for path resolution and symbolic link handling.
413
414
```kotlin { .api }
415
/**
416
* Assert that path is in canonical form (resolved, no symbolic links)
417
* @return The original File for chaining
418
*/
419
fun File.shouldBeCanonical(): File
420
421
/**
422
* Assert that path is not in canonical form
423
* @return The original File for chaining
424
*/
425
fun File.shouldNotBeCanonical(): File
426
427
/**
428
* Assert that file is a symbolic link
429
* @return The original File for chaining
430
*/
431
fun File.shouldBeSymbolicLink(): File
432
433
/**
434
* Assert that file is not a symbolic link
435
* @return The original File for chaining
436
*/
437
fun File.shouldNotBeSymbolicLink(): File
438
439
/**
440
* Create matcher for canonical path validation
441
* @return Matcher that passes for canonical paths
442
*/
443
fun beCanonical(): Matcher<File>
444
445
/**
446
* Create matcher for symbolic link validation
447
* @return Matcher that passes for symbolic links
448
*/
449
fun beSymbolicLink(): Matcher<File>
450
```
451
452
### Directory Structure Comparison
453
454
Advanced matchers for comparing directory structures and content.
455
456
```kotlin { .api }
457
/**
458
* Assert that directory has same structure as another directory
459
* Compares file and directory names recursively, ignoring content
460
* @param file The directory to compare structure against
461
* @return The original File for chaining
462
*/
463
infix fun File.shouldHaveSameStructureAs(file: File): File
464
465
/**
466
* Assert that directory does not have same structure as another
467
* @param file The directory to compare structure against
468
* @return The original File for chaining
469
*/
470
infix fun File.shouldNotHaveSameStructureAs(file: File): File
471
472
/**
473
* Assert that directory has same structure and content as another directory
474
* Compares both structure and file content recursively
475
* @param file The directory to compare against completely
476
* @return The original File for chaining
477
*/
478
infix fun File.shouldHaveSameStructureAndContentAs(file: File): File
479
480
/**
481
* Assert that directory does not have same structure and content
482
* @param file The directory to compare against
483
* @return The original File for chaining
484
*/
485
infix fun File.shouldNotHaveSameStructureAndContentAs(file: File): File
486
487
/**
488
* Create matcher for directory structure comparison
489
* @param expected The directory structure to compare against
490
* @return Matcher that passes when structures match
491
*/
492
fun haveSameStructureAs(expected: File): Matcher<File>
493
494
/**
495
* Create matcher for complete directory comparison
496
* @param expected The directory to compare completely against
497
* @return Matcher that passes when structure and content match
498
*/
499
fun haveSameStructureAndContentAs(expected: File): Matcher<File>
500
```
501
502
**Usage Examples:**
503
504
```kotlin
505
import io.kotest.matchers.file.*
506
import java.io.File
507
508
val sourceDir = File("src/")
509
val backupDir = File("backup/")
510
val templateDir = File("template/")
511
512
// Structure comparison
513
sourceDir shouldHaveSameStructureAs backupDir
514
515
// Complete comparison (structure + content)
516
backupDir shouldHaveSameStructureAndContentAs templateDir
517
518
// Path resolution validation
519
val linkFile = File("/tmp/link")
520
val canonicalFile = File("/home/user/document.txt")
521
522
linkFile.shouldBeSymbolicLink()
523
canonicalFile.shouldBeCanonical()
524
525
// Using matcher syntax
526
sourceDir should haveSameStructureAs(templateDir)
527
```
528
529
### Content-Based Validation
530
531
Matchers for validating file content and text-based operations.
532
533
```kotlin { .api }
534
/**
535
* Assert that file contains specified text content
536
* @param text The text that should be present in the file
537
* @return The original File for chaining
538
*/
539
infix fun File.shouldContainText(text: String): File
540
541
/**
542
* Assert that file does not contain specified text
543
* @param text The text that should not be present
544
* @return The original File for chaining
545
*/
546
infix fun File.shouldNotContainText(text: String): File
547
548
/**
549
* Assert that file content matches regular expression
550
* @param regex The pattern to match against file content
551
* @return The original File for chaining
552
*/
553
infix fun File.shouldMatchContent(regex: Regex): File
554
555
/**
556
* Assert that file content does not match regular expression
557
* @param regex The pattern that should not match
558
* @return The original File for chaining
559
*/
560
infix fun File.shouldNotMatchContent(regex: Regex): File
561
562
/**
563
* Assert that text file has specified number of lines
564
* @param lines Expected line count
565
* @return The original File for chaining
566
*/
567
infix fun File.shouldHaveLineCount(lines: Int): File
568
569
/**
570
* Create matcher for text content validation
571
* @param text The expected text content
572
* @return Matcher that passes when file contains the text
573
*/
574
fun containText(text: String): Matcher<File>
575
576
/**
577
* Create matcher for content pattern validation
578
* @param regex The pattern to match against
579
* @return Matcher that passes when file content matches pattern
580
*/
581
fun matchContent(regex: Regex): Matcher<File>
582
583
/**
584
* Create matcher for line count validation
585
* @param lines Expected number of lines
586
* @return Matcher that passes when file has exact line count
587
*/
588
fun haveLineCount(lines: Int): Matcher<File>
589
```
590
591
**Usage Examples:**
592
593
```kotlin
594
import io.kotest.matchers.file.*
595
import java.io.File
596
597
val configFile = File("config.properties")
598
val logFile = File("application.log")
599
val csvFile = File("data.csv")
600
601
// Content validation
602
configFile shouldContainText "database.url="
603
logFile shouldMatchContent """ERROR.*\d{4}-\d{2}-\d{2}""".toRegex()
604
csvFile shouldHaveLineCount 100
605
606
// Using matcher syntax
607
configFile should containText("server.port=8080")
608
logFile should matchContent("""INFO.*started""".toRegex())
609
```
610
611
## Error Handling
612
613
File system matchers provide comprehensive error information for assertion failures:
614
615
- **Existence failures**: Clear indication of which files/directories don't exist with path details
616
- **Permission failures**: Specific information about which permissions are missing or unexpected
617
- **Size failures**: Expected vs actual size with human-readable format (bytes, KB, MB)
618
- **Content failures**: Line-by-line differences for text content with highlighting
619
- **Structure failures**: Tree-like display of directory structure differences
620
- **Path resolution failures**: Clear explanation of canonical path vs actual path issues
621
622
All file system matchers handle I/O exceptions appropriately and convert them to meaningful assertion failures with context about the attempted operation.