Another perspective to add to the list:
One of my projects includes a year-long weekly rhythm, where I get a new set of simiarly-structured input files. The process that executes on these input files is rather lengthy, and it might take days for the first symptom of the problem to break out (thereby losing days of processing), so finding violations of my assumptions early is rather important.
If the code were mine, then when I find a problem with the files, the first thing I would do is file an issue/bug, write a test to catch the mistake in generation, fix the bug, then move on. Since the code is not mine, I can only test against the data instead of the code.
So I've adopted using
testthat on my input files. (I'm sure other unit-tests could be similarly adapted.) Since the names and structure of each of the files is static-enough for the tests, it's rather straight-forward. Furthermore,
testthat provides good mechanisms for automation and returning problems in easily-digested (and if desired verbose) formats for quick identification of problems.
It's not hard to conceive some of these tests up-front: type (int, string, bool), min/max size (exactly 1, no less than 10, no more than 52), and sets (only allow specific values). While I can think of a million other ways that the data might go wrong, I cannot guard against (or check) all of these. So my template starts with the basics: type, size, and sets. If there are obvious boundary values (e.g., always non-negative) then I can incorporate those, but for the most part any test after those defaults are to guard against a failure that I've actually seen (and not just imagined).
(I won't go into how to do write a personal function to adapt these types of tests onto a dataset, the website is pretty robust with examples.)