Proper ADTs are extremely important imho, and you can address the testing part generally by moving tests to the definition module instead of keeping it outside. Though some languages (like Swift) let you violate boundaries in test code, which is an okay approach too.