Writing code constitutes less than half the cost of developing a modern software application. Programmers must also be able to rigorously test, debug, and secure large, complex codebases. This course explores tools and techniques to empower programmers in these endeavors and thereby enable them to become better software engineers.

At the heart of this course is a body of work called software analysis which concerns automatically discovering useful properties of a given program. Many diverse software analysis approaches exist, each with their own strengths, limitations, and applications to testing, debugging, performance, and security.

This course teaches the underlying principles of software analysis, and provides hands-on experience applying them to automate testing software and finding bugs in complex, real-world programs. You will learn how to check and eliminate entire classes of programming errors before deploying code, how to exploit randomization to discover harmful security vulnerabilities and non-deterministic concurrency bugs, how to exhaustively test libraries and data structures, and how to automatically isolate root causes in complex crashing test cases.

The course covers state-of-the-art techniques for random testing, dataflow analysis, constraint-based analysis, type systems, automated test case generation, symbolic execution, and more. Knowing how these techniques work and when to apply them will enhance your software development skills both as an individual and as a part of a team building large, critical software products.

In general, this course introduces software analysis and testing topics in the order in which they can be integrated into a software development lifecycle.

The lessons focus on advanced techniques that go far beyond established practices like manual code reviews, unit testing, and integration testing to find bugs (and security vulnerabilities!) in software.

Most lessons are complemented by a short term assignment that leverages an existing tool or library to reinforce the concepts learned in the lesson. It is useful to think of the assignments as “science labs” - they are meant to bridge the gap between theory and practice as well as deepen your understanding of the material.

In this course, you will use a variety of tools implemented in different programming languages to generate useful facts about a program’s behavior and analyze them. This means you should be comfortable reading and writing basic code in several commonly used languages, such as C, Java and Python. In preparation for taking this course, we recommend that you visit our Readiness Assessment to determine which skills you may wish to refresh or acquire prior to the start of classes.