Skip to content

Unit 3 Quiz

The goal of this page is to provide you with a single source of guidance on what to review and prepare for ahead of Quiz 3. The goal of the quiz is to assess your understanding of key concepts, ideas, and skills we have covered since the last quiz.

Task Learning Objectives

The emphasis since the last quiz has been on Task 7: refactoring an existing layered web application from a temporary flat-file persistence layer to a PostgreSQL-backed ORM persistence layer.

TK07 - Refactor Persistence Layer to an ORM

After completing this task, you should be able to:

  1. Explain why replacing the persistence layer beneath an existing API is a refactoring rather than a full rewrite.
  2. Distinguish the responsibilities of routes, services, and entities in an ORM-backed architecture.
  3. Explain why the old store layer and its tests should be completely removed once persistence responsibilities move into services backed by database sessions.
  4. Describe how a service layer can coordinate reads and writes through a Session while preserving clean separation from HTTP concerns.
  5. Explain why route handlers can often remain mostly unchanged during this refactor even though the service implementation and many tests must change.
  6. Describe a pragmatic incremental workflow for a risky refactor: branch the work, replace one service method at a time, manually verify it, then add focused integration tests.
  7. Explain why service-layer tests in this task are integration tests against a real database rather than isolated unit tests.
  8. Describe what the task expects from route-level end-to-end tests once the ORM-backed service layer is in place.
  9. Explain the value of scripts/run-qa.sh, 100% test coverage, and verifying the full feature manually through the running development server.
  10. Connect the assignment's required outcomes back to the larger engineering goals of layered design, refactoring, and confidence through testing.

Lesson Learning Objectives

LS16 - Introduction to Object-Relational Mapping

After this lesson, you should be able to:

  1. Explain what an ORM is and what problem it solves between Python objects and relational database tables.
  2. Identify the major logical components in an ORM-backed stack, including entities, sessions, engines, SQLModel / SQLAlchemy, and the database itself.
  3. Distinguish API-facing models from persistence entities.
  4. Read and interpret a basic SQLModel query using select(), col(), .where(), and session.exec().
  5. Explain the role of an engine as the application's entry point to the database.
  6. Explain the role of a session as a unit-of-work or workspace for database operations.
  7. Trace a request from FastAPI routing through a service method to the generated SQL query and database response.

LS17 - Testing with an ORM

After this lesson, you should be able to:

  1. Explain why the web service and the database are two integrated systems that must be considered together in development and testing.
  2. Describe how Docker Compose is used to run a multi-container development environment with both an application service and a database service.
  3. Explain why database-backed service tests in this unit are integration tests rather than pure unit tests.
  4. Describe the purpose of fixtures that provide engines, sessions, schema setup, and schema teardown.
  5. Explain why function-scoped test isolation matters when testing with a real database.
  6. Use coverage information to identify missing expected-case or edge-case tests in a service module.
  7. Explain the role of helper functions and seed data helpers in arranging realistic test state without introducing shared mutable state across tests.

LS18 - ORM Tools

After this lesson, you should be able to:

  1. Explain why both database integration tests and route-level end-to-end tests are valuable.
  2. Recognize that database tooling and environment setup are part of the software architecture, not just incidental setup work.

LS19 - TK07 Lab Day

Content covered in TK07.

LS20 - Entity Relationships in an ORM

After this lesson, you should be able to:

  1. Explain how SQLModel relationships can be explored interactively using a notebook or REPL.
  2. Describe how relationship access interacts with the session's identity map and cached object state.
  3. Explain why the first access to related data may trigger a database query while later accesses may reuse already loaded state.
  4. Connect interactive observations of related objects back to relationship declarations such as Relationship() and foreign keys.

LS21 - Container Fundamentals

After this lesson, you should be able to:

  1. Explain why containers help create reproducible development and deployment environments.
  2. Distinguish a Docker image from a Docker container.
  3. Explain why containers are isolated processes rather than miniature virtual machines.
  4. Describe the role of namespaces and control groups at a high level.
  5. Explain the "one container = one primary process" design model.
  6. Describe how Docker behaves differently on Linux versus macOS and Windows.
  7. Explain how Docker images are built from Dockerfiles using layers.
  8. Distinguish a container's writable layer from a volume used for durable data.
  9. Explain basic container networking and port publishing.
  10. Describe the basic lifecycle of a container from creation to removal.

Reading Learning Objectives

RD20 - SQL Primer for COMP423

You should be able to:

  1. Explain the relational model in practical software engineering terms.
  2. Differentiate between a primary key and a unique constraint.
  3. Describe what an index does and why indexed lookups are faster.
  4. Predict what happens when a uniqueness constraint is violated.
  5. Explain what a foreign key constraint enforces and what happens when it is violated.
  6. Write and interpret SQL queries for filtering, sorting, updating, and aggregating data.
  7. Write a multi-statement SQL transaction using BEGIN and COMMIT and describe ACID properties at a high level.

RD21 - Querying with SQLModel

You should be able to:

  1. Translate a SELECT ... FROM ... WHERE SQL query into a SQLModel select() statement.
  2. Explain the difference between building a query with select() and executing it with session.exec().
  3. Use .all(), .first(), and .one() appropriately when consuming query results.
  4. Use session.get() for primary-key lookups and explain why it is especially appropriate for that use case.
  5. Apply filtering with .where() and sorting or limiting with query-builder methods.
  6. Explain the role of col() in building SQLModel expressions.
  7. Translate SQL INSERT and UPDATE behavior into SQLModel operations such as session.add() and attribute assignment.
  8. Recognize that SQLModel uses Python operator overloading to build SQL expressions rather than ordinary boolean comparisons.

RD22 - Engines, Sessions, and Transactions in SQLModel / SQLAlchemy

You should be able to:

  1. Explain what an engine is and its role in database connectivity.
  2. Describe the relationship between an engine and a session.
  3. Explain what a session represents as a unit of work.
  4. Describe what commit() does.
  5. Explain what happens if you forget to commit.
  6. Explain what refresh() does and when it is needed.
  7. Describe transaction boundaries in web applications.
  8. Explain why session-per-request is a best practice.
  9. Explain how Docker Compose service names become hostnames in a database connection string.
  10. Describe what a Docker named volume provides for database persistence.

RD23 - Testing with Databases

You should be able to:

  1. Explain why testing services against a real database is valuable.
  2. Understand the motivation for generating a fresh schema per test.
  3. Explain why tests can pass individually but fail as part of a suite when isolation is poor.
  4. Distinguish strict unit tests from database-backed integration tests and explain why both can be useful.
  5. Identify anti-patterns such as global sessions and shared test state.
  6. Decide when asserting a method's return value is sufficient and when you should also verify persisted database state.
  7. Explain the role of seeding data and helpers in arranging realistic but isolated tests.

RD24 - Introduction to Entity Relationships in an ORM

You should be able to:

  1. Explain what a foreign key is and why it matters.
  2. Describe one-to-many relationships conceptually and in SQLModel.
  3. Explain how ORMs represent relationships with Relationship().
  4. Work with related entities from either side of a relationship in Python.
  5. Explain what back_populates does for synchronized object state.
  6. Recognize how relationship traversal can trigger the N+1 queries problem.
  7. Write or interpret basic relationship queries using joins and filters.
  8. Explain, at a high level, how SQLModel / SQLAlchemy handle inserts across related entities.
  9. Describe how many-to-many relationships use join tables.
  10. Explain the basics of delete and delete-orphan cascade behavior.
  11. Identify when normalization is necessary.

Quiz Format

The constrained choice questions will primarily assess your understanding of the readings and core conceptual distinctions across SQL, SQLModel, sessions, testing, relationships, and containers.

The open ended questions will primarily assess your understanding of the work you completed in TK07 and the hands-on ideas reinforced in lecture.

As with prior quizzes, you should be prepared to:

  1. Describe software behavior in technically precise English.
  2. Explain what a particular test verifies or proves.
  3. Describe the Arrange, Act, and Assert steps for database-backed testing scenarios.
  4. Explain why a design choice or testing strategy is appropriate in a layered ORM-backed application.