Doing IO stuff is very well-supported in Haskell. Printing to the terminal just looks like:
main = putStrLn "Hello World" main = putStrLn "Hello World"There are other approaches you can take too, like encoding your effects in a monad which has a different runtime representation in tests. It's like mocking on steroids with type safety.
This doesn't negate the advantages of tracking effectful code in the type system, and there's still plenty of code that can be pure.