25-Comp-A6 Software Engineering · December 2016
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
National Exams — December 2016 — 98-Comp-A6 Software Engineering. Three-hour, closed-book exam, no calculator permitted. Format: eight questions, candidates answer any five of the eight (all questions equal weight — each of the five counted questions is worth 20%; only the first five questions as they appear in the answer book are marked). All eight questions are solved below for completeness.
Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software process models, object-oriented and function-oriented design, software testing, component-based software engineering, verification and validation, distributed software engineering, software evolution/maintenance; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process, testing and architecture coverage; Gamma, Helm, Johnson & Vlissides, Design Patterns — object-oriented design/reuse vocabulary.
Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.
A test suite exercises the program on a finite, chosen subset of its (typically astronomically large or infinite) input space. If any test in that subset fails, the program is provably incorrect — a single failing test is a valid proof of a defect. But if every chosen test passes, that only shows the program behaves correctly on the inputs actually tried; it says nothing about the inputs that were never tried, any one of which could still trigger a defect. Since it is generally infeasible to test every possible input (or every possible execution path/state), passing all tests can never be used to conclude the program is defect-free — only that no defect has yet been found by this particular finite sample.
Regression testing is re-running a system's existing test suite after a change (a bug fix, a new feature, a refactor) specifically to check that the change has not broken any previously working behaviour — that the system has not "regressed." It is necessary because software components are rarely as independent as their interfaces suggest: a change made for one purpose can have unintended side effects on unrelated parts of the system through shared state, a changed data format, or a subtle timing dependency, and the only reliable way to catch such a side effect is to re-verify everything that was already known to work, not just the area that was deliberately changed.
Run entirely by hand, regression testing is expensive in direct proportion to how large the existing test suite has grown, which creates a perverse incentive to skip it, run only a hand-picked subset, or run it rarely — exactly the situations in which a regression is most likely to slip through. An automated test suite (each test coded so it runs and checks its own expected result without a human operator) plus a testing framework (the harness that discovers, executes, and reports every test's pass/fail status in one run) removes that cost: the full suite can be re-run after every single change, in minutes, with no incremental human effort per run, which is precisely why continuous-integration pipelines re-run the whole regression suite on every commit rather than only before a release. Automation also makes regression testing repeatable in the strict sense — the same test executes the same steps and applies the same pass/fail criterion every time, removing the variability of a human tester re-deriving "does this still look right" by eye on each run, which both catches subtler regressions and makes a failure immediately attributable to the specific change that introduced it.
| Test case | Purpose |
|---|---|
| Empty array | Boundary: zero elements |
| Single-element array | Boundary: trivially sorted |
| Already-sorted array | Best-case / no-op behaviour |
| Reverse-sorted array | Worst-case ordering |
| Array with duplicate values | Stability/tie-handling of equal keys |
| Array with negative and positive values | Correct ordering across sign |
| Array with all identical elements | Degenerate case, no distinct ordering |
| Array containing INT_MIN / INT_MAX | Boundary values of the integer type |
| Large random array | General-case correctness at scale |
| Test case | Purpose |
|---|---|
| Empty line | Boundary: zero-length input, expect count 0 |
| Line of all blanks | Expect count 0 |
| Line with no blanks at all | Expect count = line length |
| Line with mixed blank and non-blank characters | General case |
| Line with leading and/or trailing blanks | Blanks at the boundary of the string, not just interior |
| Line containing tab characters | Clarifies whether "blank" means space only or any whitespace |
| Line with punctuation/special characters | Confirms non-space, non-alphanumeric characters are counted as non-blank |
| Single-character line | Boundary: smallest non-empty input |
| Very long line | General-case correctness / buffer handling at scale |
| Input | Expected result | Purpose |
|---|---|---|
| 2011/1/1 | Valid | Given worked example — single-digit month and day, both allowed |
| 1990/12/25 | Valid | Given worked example — two-digit month and day |
| 1250/03/18 | Valid | Given worked example — leading zero on a two-digit month |
| 2016/02/29 | Valid | Boundary: February 29 in a leap year (2016 divisible by 4) |
| 2015/02/29 | Invalid | Boundary: February 29 in a non-leap year |
| 2000/02/29 | Valid | Century-year leap-rule boundary (2000 is divisible by 400, hence a leap year despite being a century year) |
| 1900/02/29 | Invalid | Century-year leap-rule boundary (1900 is divisible by 100 but not 400, hence NOT a leap year) |
| 2014/00/15 | Invalid | Boundary: month 0 is out of range |
| 2014/13/15 | Invalid | Boundary: month 13 is out of range |
| 2014/04/00 | Invalid | Boundary: day 0 is out of range |
| 2014/04/31 | Invalid | Day out of range for a 30-day month |
| 201/05/12 | Invalid | Year is only 3 digits — spec requires exactly 4 |
| 20145/05/12 | Invalid | Year is 5 digits — spec requires exactly 4 |
| 2014/5/012 | Invalid | Day has 3 digits — spec allows only 1 or 2 |
| 2014 / 5 / 1 | Valid | Spaces around the digit groups are explicitly to be ignored per the spec |
| 2014-05-01 | Invalid | Wrong separator character (hyphen instead of slash) |
| 2014//5/1 | Invalid | Malformed separators / missing field |