A module is the fundamental construct used for building designs. Each module can contain hierarchies of other modules, nets, variables and other procedural blocks to describe any hardware functionality. The testbench on the other hand is a complete environment to verify the design and hence an emphasis is placed on the way it is modeled to make it more re-usable and effective. It must be properly initialized and synchronized, avoiding race conditions between the design and the testbench.
Three main reasons for having a program block :
To provide an entry point to the execution of testbenches
To create a container to hold all other testbench data such as tasks, class objects and functions
Avoid race conditions with the design by getting executed during the reactive region of a simulation cycle