Looking back at how software was built and deployed even 15 years ago, it seems surprising that our applications actually worked. In those days a software development lifecycle consisted of running builds on a local machine, manually copying the artifacts to a staging server, and manually testing each application through multiple iterations. When the dev team was satisfied with the build, we would manually deploy the application into production. The most consistent thing about this style of development was inconsistency--in process and in results.
Over a decade ago, agile developers began to embrace and promote test-driven development and continuous integration (CI). With these techniques we could automatically build source code whenever a developer checked it into a source repository, executing an exhaustive unit test suite to ensure that an application was working properly. Many test-driven developers also started doing integration testing and performance testing in a secondary CI process.