The biggest difficulty is trying to create good test cases. Unlike normal tests where you're asserting that some specific case is true, with quickcheck-style tests, you're instead trying to find an invariant in your code that will always be true. So it's quite easy to do "this algorithm never throws an error" but harder to do "this algorithm returns true in these cases and false in these cases". That said, a lot of tools in this space give you a lot of flexibility for generating cases, like saying "generate strings matching this regex" or "generate these arbitrary primitives and map then into the correct structure with this function".
The randomness involved isn't ideal, because you can't necessarily guarantee that the same errors will always show up every time, but it's a good habit to copy the failing generated case into its own test as a kind of regression test. And obviously still write a lot of the standard test cases for more obvious problem points.
I'd definitely love to use it more though, it's one of those things I come back to every so often, unfortunately thus far without much success.
One problem though is that being better at finding bugs isn’t always great: if you find bugs you might feel the desire to fix them but for many software teams, having rare bugs is acceptable, even if they aren’t rare in absolute terms (ie a 1-in-10,000,000 when you have a billion chances for it to happen a day)
Now that is testing.
I recently got a tip from someone who recently worked on a project I was at that he had a suspicion some validation code didn't cover all all cases.
There were maybe tre tests which where all green.
So I generated 50 random, but known valid cases and, voila, a few of them failed.
From there it was easy to fix the issue.