Skip to content

Session 8

Unit, module, and integration test cases for the matrix multiplication program

Updated View as Markdown

This session produces a set of test cases for the program written in Session 7, organised at three levels: unit tests for each function, module tests for the multiplication module as a whole, and integration tests for the complete program with its input and output. Every test case has an expected output written before the run and an actual output recorded after it, so the record shows evidence, not intentions. The program is small, but the same table structure is what you would use for the Railway Reservation System in Session 15.

Objectives

Do not copy. Read for understanding and the viva
  • Tell the three levels apart: what a unit, a module, and an integration test each check
  • Write a test case with a precondition, an input, an expected output, and a status
  • Cover boundary values (1 x 1, the maximum dimension), invalid input (zero, mismatch, letters), and large values
  • Run every case, record the actual output, and report defects honestly
  • Produce a test summary and a defect log the examiner can verify against the program

Problem Statement

Write in lab record

Develop a set of test cases that will completely test the program in session 7. The test case should be separately developed for Unit testing, Module testing and Integration testing.

Concept

Do not copy. Read for understanding and the viva

The three levels

Unit testing checks one function in isolation, called directly from a small test driver, with the rest of the program out of the way. Module testing checks a group of functions that work together, here the multiplication module: read_dim, read_matrix, multiply, print_matrix, and free_matrix operating on real allocated matrices. Integration testing checks the whole program as the user runs it: input through stdin, output on stdout, exit status.

How unit tests are run on a C program

main reads from the keyboard, so a unit test cannot go through it. The driver is a second C file that includes matrix_multiply.c with main renamed (#define main prog_main before the include) and then calls multiply, print_matrix, and free_matrix on arrays it builds itself. For read_matrix and read_dim, the driver is fed input through a pipe: printf '1 2\n3 4\n' | ./driver. Record the driver command with the test case so the examiner can repeat it.

Choosing inputs

For every function, pick one normal case, the smallest legal size, an invalid input, and, where numbers are involved, a large value. The point of the large value is to find the overflow limit of int, not to avoid it. A test that only uses 1, 2, 3 proves very little.

What “actual output” means

Copy the real output, not a paraphrase. If a case fails, the actual output column shows what went wrong, and the defect log explains it. A test record with 100 percent pass and no defects on a first run is usually a sign of weak tests, not perfect code.

Unit Test Cases

Write in lab record

Driver: ut.c includes matrix_multiply.c with main renamed, builds arrays in code, and calls each function. Built with gcc -Wall -Wextra -o ut ut.c.

TC idFunctionPreconditionInputExpected outputActual outputStatus
UT-01read_dimstdin piped5returns 1, stores 5ok=1 d=5Pass
UT-02read_dimstdin piped100 (upper bound)returns 1, stores 100ok=1 d=100Pass
UT-03read_dimstdin piped0prints range error, returns 0“Error: dimension must be between 1 and 100.” ok=0Pass
UT-04read_dimstdin piped101prints range error, returns 0“Error: dimension must be between 1 and 100.” ok=0Pass
UT-05read_dimstdin pipedabcprints integer error, returns 0“Error: dimension must be an integer.” ok=0Pass
UT-06read_dimstdin piped2.5rejected as not a whole numberok=1 d=2, .5 left in bufferFail (D-02)
UT-07read_matrixrows=2, cols=2, stdin piped1 2 newline 3 4block holds 1 2 3 4 in row-major orderstored: 1 2 3 4Pass
UT-08read_matrixrows=2, cols=2, stdin piped1 2 x 4error naming element (2,1), returns NULL“Error: element (2,1) is not an integer.” returned NULLPass
UT-09read_matrixrows=2, cols=2, stdin piped1 2 then end of inputerror, returns NULL, no crash“Error: element (2,1) is not an integer.” returned NULLPass (see D-03)
UT-10read_matrixrows=2, cols=2, stdin piped9 -9 0 2147483647negative, zero and INT_MAX stored exactlystored: 9 -9 0 2147483647Pass
UT-11multiplya = 1 2 3 4 5 6 (2 x 3), b = 7 8 9 10 11 12 (3 x 2), c allocated 2 x 2r1=2 c1=3 c2=2c = 58 64 139 15458 64 139 154Pass
UT-12multiplya = 7, b = 6 (1 x 1 each)r1=c1=c2=1c = 4242Pass
UT-13multiplya = identity 2 x 2, b = 5 6 7 8r1=c1=c2=2c equals b: 5 6 7 85 6 7 8Pass
UT-14multiplya = all zeros 2 x 2, b = 5 6 7 8r1=c1=c2=2c = 0 0 0 00 0 0 0Pass
UT-15multiplya = -3 4 (1 x 2), b = 2 -5 (2 x 1)r1=1 c1=2 c2=1c = -26-26Pass
UT-16multiplya = 100000, b = 100000 (1 x 1)r1=c1=c2=110000000000 or an overflow error1410065408Fail (D-01)
UT-17print_matrixm = 7 (1 x 1)title “UT-P1”header line then 7“UT-P1 (1 x 1):” newline ” 7”Pass
UT-18print_matrixm = 1 2 3 4 5 6 (2 x 3)title “UT-P2”two rows of three right-aligned width-6 numbers” 1 2 3” newline ” 4 5 6”Pass
UT-19print_matrixm = -3 4 (1 x 2)title “UT-P3”negative printed with sign, aligned” -3 4”Pass
UT-20free_matrixnoneNULLno crash, returnsreturned normallyPass
UT-21free_matrixm from malloc of 4 intsvalid pointermemory released, no crashreturned normallyPass

Module Test Cases

Write in lab record

Module under test: the multiplication module, that is read_dim + read_matrix + multiply + print_matrix + free_matrix working together on matrices that were really allocated and really read from input. These are run through main but each case targets one path through the module rather than the user experience.

TC idFeaturePreconditionInputExpected outputActual outputStatus
MT-01Read, multiply, print, free for rectangular matricesprogram builtdims 2 3 3 2; A = 1 2 3 4 5 6; B = 7 8 9 10 11 12Product printed as 58 64 over 139 154; exit 0Product A x B (2 x 2): 58 64 / 139 154; exit 0Pass
MT-02Smallest matrices flow through every functionprogram builtdims 1 1 1 1; A = 7; B = 6Product (1 x 1): 42; exit 0Product A x B (1 x 1): 42; exit 0Pass
MT-03Dimension check stops the module before allocationprogram builtdims 2 3 2 2mismatch error naming 3 and 2; no element prompt; exit 1“Error: columns of A (3) must equal rows of B (2). Multiplication not possible.”; exit 1Pass
MT-04Zero dimension rejected before anything is readprogram builtdims 0range error after first prompt; exit 1“Rows of A: Error: dimension must be between 1 and 100.”; exit 1Pass
MT-05Bad element in A frees A and stopsprogram builtdims 1 1 1 1; A = xelement error; no prompt for B; exit 1“Error: element (1,1) is not an integer.”; exit 1Pass
MT-06Negative elements pass through unchangedprogram builtdims 1 1 1 1; A = -3; B = 4Product -12Product A x B (1 x 1): -12Pass
MT-07Large productprogram builtdims 1 1 1 1; A = 100000; B = 10000010000000000 or an overflow message1410065408Fail (D-01)
MT-08Maximum dimension allocationprogram builtdims 100 100 100 100, all elements 1100 x 100 product of all 100s; exit 0100 x 100 matrix of 100 printed; exit 0Pass

Integration Test Cases

Write in lab record

Whole program as the user runs it: ./matrix_multiply from a terminal, typed input, observed output and exit code.

TC idFeaturePreconditionInputExpected outputActual outputStatus
IT-01Normal end-to-end runbinary built with no warnings2, 3, 3, 2 then the two matrices from the Session 7 sampleA, B and the product all printed with labels and sizes; exit 0Matrix A (2 x 3), Matrix B (3 x 2), Product A x B (2 x 2) with 58 64 / 139 154; exit 0Pass
IT-02Square matricesbinary built2, 2, 2, 2; A = 1 2 3 4; B = 5 6 7 819 22 / 43 5019 22 / 43 50Pass
IT-03Prompts appear in order and stop at the first bad valuebinary built2, 3, 2, 2four prompts, then mismatch error, no element promptPrompts for all four dims then the mismatch error; exit 1Pass
IT-04Letters for a dimensionbinary builtabcinteger error at the first prompt; exit 1“Rows of A: Error: dimension must be an integer.”; exit 1Pass
IT-05Dimension above the limitbinary built101range error; exit 1“Error: dimension must be between 1 and 100.”; exit 1Pass
IT-06Input ends earlybinary built2, 2, 2, 2 then only three elementserror, no crash, exit 1“Error: element (2,2) is not an integer.”; exit 1Pass (see D-03)
IT-07Output alignmentbinary built1, 1, 1, 1; A = 100000; B = 100000numbers wider than 6 still printed on their own line“100000” and “1410065408” printed; alignment holds, value wrongFail (D-01)
IT-08Build checksource filegcc -Wall -Wextra -o matrix_multiply matrix_multiply.cno warnings, binary producedcompiled, no output from gccPass

Test Summary

Write in lab record
LevelCases writtenCases runPassedFailedPass rate
Unit212119290%
Module887188%
Integration887188%
Total373733489%

The four failures are two defects (D-01 appears at all three levels, D-02 at unit level only). D-03 is an observation, not a failure.

Defect Log

Write in lab record
Defect idFound byDescriptionSeverityRoot causeSuggested fixStatus
D-01UT-16, MT-07, IT-07100000 x 100000 prints 1410065408 instead of 10000000000.Mediumsum is a long but is cast to int when stored in C, and C is an int block. Any product above 2147483647 wraps.Store the result matrix as long and print with %ld, or detect sum outside the int range and report an overflow error.Open
D-02UT-06Dimension 2.5 is accepted as 2.Lowscanf("%d") reads the 2 and leaves .5 in the input buffer, which then breaks the next read.Read the line with fgets and parse with strtol, rejecting any trailing characters.Open
D-03UT-09, IT-06When input ends early, the message says the element “is not an integer”, which is misleading; the real cause is missing input.Low (observation)scanf returns EOF and the code treats every non-1 return as non-numeric.Check for EOF separately and print “unexpected end of input”.Noted

No crashes, hangs, or memory errors were found in any case. The dimension check and the row-major pointer walk behaved correctly in every valid and invalid case.

Viva Questions

Do not copy. Read for understanding and the viva
  • Q: What is the difference between a unit test and a module test here? A: A unit test calls one function from a driver with hand-built arrays; a module test runs the read, multiply, print, and free functions together on real input.
  • Q: Why does the unit driver rename main? A: So the driver can have its own main and call the program’s functions directly.
  • Q: What is a precondition? A: The state that must hold before the test runs, such as “binary built” or “rows=2, cols=2”.
  • Q: Why include 1 x 1 matrices? A: It is the smallest legal size; loops that run once expose off-by-one errors.
  • Q: Why is D-01 medium and not low? A: It produces a wrong answer silently; the user has no way to tell the output is wrong.
  • Q: Does a failing test mean the session failed? A: No. Finding and recording a real defect is the purpose of testing.
  • Q: What does the pass rate measure? A: The share of test cases whose actual output matched the expected output; it says nothing about how good the cases are.
  • Q: Why record the exit status? A: It is the program’s contract with the shell; a script calling this program would rely on 0 for success and 1 for error.

Common Mistakes

Do not copy. Read for understanding and the viva
  • Writing expected output after seeing the actual output, so every case passes by construction.
  • Testing only happy paths. The mismatch, zero, letters, and large-value cases are where the defects live.
  • Putting the same case at all three levels and calling it three tests. Each level must target something the others cannot see.
  • Leaving the actual output column blank or writing “as expected”. Copy the real text.
  • Ignoring compiler warnings as if they were not defects. IT-08 exists so the build itself is a test.
  • Marking an overflow as pass because “the program did not crash”. Wrong output is a failure.

Session Summary

Write in lab record
  • Unit test table (21 cases) with the driver command
  • Module test table (8 cases)
  • Integration test table (8 cases)
  • Test summary table with counts per level
  • Defect log with D-01 to D-03, each with severity and suggested fix
Navigation

Type to search…

↑↓ navigate↵ selectEsc close