17. Software Testing
What is Test Automation?
The use of software to control the execution of tests, the comparison of actual outcomes to predicted outcomes, the setting up of test preconditions, and other test control and test reporting functions
Software๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ์คํ์ ์ ์ดํ๊ณ , ์ค์ ๊ฒฐ๊ณผ์ ์์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ๋ฉฐ, ํ ์คํธ ์ ์ ์กฐ๊ฑด(preconditions) ์ค์ ๋ฐ ๊ธฐํ ํ ์คํธ ์ ์ด/๋ณด๊ณ ๊ธฐ๋ฅ์ ์ํ
- Cost ์ ๊ฐ
- Human error ๊ฐ์
- ๊ฐ์ธ๋ณ Test quality ํธ์ฐจ ๊ฐ์
- Regression testing ๋น์ฉ์ ํ๊ธฐ์ ์ ๊ฐ
Software Testability
The degree to which a system or component facilitates the establishment of test criteria and the performance of tests to determine whether those criteria have been met
System ๋๋ component๊ฐ ํ ์คํธ ๊ธฐ์ค์ ์๋ฆฝํ๊ณ , ํด๋น ๊ธฐ์ค์ด ์ถฉ์กฑ๋์๋์ง ํ์ธํ๊ธฐ ์ํ ํ ์คํธ ์ํ์ ์ฉ์ดํ๊ฒ ํ๋ ์ ๋
- ์ฝ๊ฒ ๋งํด software์์ ๊ฒฐํจ์ ์ฐพ๊ธฐ๊ฐ ์ผ๋ง๋ ์ด๋ ค์ด์ง๋ฅผ ์๋ฏธ
- Testability๋ฅผ ์ง๋ฐฐํ๋ ๋ ๊ฐ์ง ์ค์ง์ ์ธ ๋ฌธ์
- Software์ test values๋ฅผ ์ด๋ป๊ฒ ์ ๊ณตํ ๊ฒ์ธ๊ฐ
- ํ ์คํธ ์คํ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ป๊ฒ ๊ด์ฐฐํ ๊ฒ์ธ๊ฐ
Observability and Controllability
- Observability
How easy it is to observe the behavior of a program in terms of its outputs, effects on the environment and other hardware and software components
- Hardware devices, Databases, ์๊ฒฉ ํ์ผ์ ์ํฅ์ ๋ฏธ์น๋ Software๋ Observability๊ฐ ๋ฎ์.
- Controllability
How easy it is to provide a program with the needed inputs, in terms of values, operations, and behaviors
- Keyboard ์ ๋ ฅ์ ํตํ Software ์ ์ด๋ ์ฌ์
- Hardware sensors๋ ๋ถ์ฐ Software๋ก๋ถํฐ์ ์ ๋ ฅ์ ์ ์ด๊ฐ ๋ ์ด๋ ค์
- Data abstraction์ Controllability์ Observability๋ฅผ ๊ฐ์์ํด
Observability and Controllability (Definition)
- ์ถ๋ ฅ, ํ๊ฒฝ์ ๋ฏธ์น๋ ์ํฅ, ๊ธฐํ Hardware ๋ฐ Software components ์ธก๋ฉด์์ ํ๋ก๊ทธ๋จ์ ๋์์ ๊ด์ฐฐํ๊ธฐ๊ฐ ์ผ๋ง๋ ์ฌ์ด๊ฐ (Observability)
- ๊ฐ, ์ฐ์ฐ, ๋์ ์ธก๋ฉด์์ ํ๋ก๊ทธ๋จ์ ํ์ํ ์ ๋ ฅ์ ์ ๊ณตํ๊ธฐ๊ฐ ์ผ๋ง๋ ์ฌ์ด๊ฐ (Controllability)
Components of a Test Case
- Test case๋ ๋ช ํํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ๋ค์ค ๋ถ๋ถ Artifact
- Test case values
- Expected results
- Test oracle์ Expected results๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ํต๊ณผ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํจ.
- Software๊ฐ ์์๋๋ก ๋์ํ ๋ ์์ฑ๋์ด์ผ ํ๋ ๊ฒฐ๊ณผ
- ํ ์คํธ ์ค์ธ Software์ ์คํ์ ์๋ฃํ๋ ๋ฐ ํ์ํ ์ ๋ ฅ ๊ฐ
Affecting Controllability and Observability
- Prefix values
Software๊ฐ Test case values๋ฅผ ๋ฐ์ ์ ์๋ ์ ์ ํ ์ํ๊ฐ ๋๋๋ก ํ๋ ๋ฐ ํ์ํ ์ ๋ ฅ
- Postfix values
Test case values๊ฐ ์ ์ก๋ ํ Software๋ก ์ ์ก๋์ด์ผ ํ๋ ์ ๋ ฅ
- Verification Values: Test case values์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ ๋ฐ ํ์ํ ๊ฐ
- Exit Values: ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํ๊ฑฐ๋ ์์ ์ ์ธ ์ํ๋ก ๋๋๋ฆฌ๋ ๋ฐ ํ์ํ ๊ฐ ๋๋ ๋ช ๋ น
Putting Tests Together
- Test case
The test case values, prefix values, postfix values, and expected results necessary for a complete execution and evaluation of the software under test
ํ ์คํธ ์ค์ธ Software์ ์์ ํ ์คํ ๋ฐ ํ๊ฐ์ ํ์ํ Test case values, Prefix values, Postfix values, Expected results - Test set
A set of test cases
Test cases์ ์งํฉ - Executable test script
A test case that is prepared in a form to be executed automatically on the test software and produce a report
ํ ์คํธ Software์์ ์๋์ผ๋ก ์คํ๋๊ณ ๋ณด๊ณ ์๋ฅผ ์์ฑํ ์ ์๋ ํํ๋ก ์ค๋น๋ Test case
Test Automation Framework
A set of assumptions, concepts, and tools that support test automation
Test automation์ ์ง์ํ๋ ๊ฐ์ , ๊ฐ๋ ๋ฐ ๋๊ตฌ์ ์งํฉ
What is JUnit?
- ๋ฐ๋ณต ๊ฐ๋ฅํ Automated tests๋ฅผ ์์ฑํ๊ณ ์คํํ๋ ๋ฐ ์ฌ์ฉ๋๋ Open source Java testing framework (ํ์ค)
- JUnit ๊ธฐ๋ฅ์ด ํฌํจํ ์ฌํญ๋ค
- Expected results ํ ์คํธ๋ฅผ ์ํ Assertions
- ๊ณตํต Test data ๊ณต์ ๋ฅผ ์ํ ํ ์คํธ ๊ธฐ๋ฅ
- ํ ์คํธ๋ฅผ ์ฝ๊ฒ ๊ตฌ์ฑํ๊ณ ์คํํ๊ธฐ ์ํ Test suites
- ๊ทธ๋ํฝ ๋ฐ ํ ์คํธ ๊ธฐ๋ฐ Test runners
- ์ฐ์ ๊ณ์์ ๋๋ฆฌ ์ฌ์ฉ๋จ
- ๋ ๋ฆฝํ Java ํ๋ก๊ทธ๋จ(Command line)์ผ๋ก ์ฌ์ฉํ๊ฑฐ๋ Eclipse, VSCode, IntelliJ ๋ฑ IDE ๋ด์์ ์ฌ์ฉ ๊ฐ๋ฅ
JUnit Tests
- JUnit ํ
์คํธ ๋์
- ์ ์ฒด Object
- Object์ ์ผ๋ถ (Method ๋๋ ์ํธ ์์ฉํ๋ Methods)
- ์ฌ๋ฌ Objects ๊ฐ์ ์ํธ ์์ฉ
- ์ฃผ๋ก System testing์ด ์๋ Unit testing ๋ฐ Integration testing์ ์ํด ์๋๋จ
- ๊ฐ ํ ์คํธ๋ ํ๋์ Test method์ ํฌํจ๋จ
- Test class๋ ํ๋ ์ด์์ Test methods๋ฅผ ํฌํจ.
- Test classes ํฌํจ ์ฌํญ
- Test methods์ ์งํฉ
- ๊ฐ ํ ์คํธ ์ ํ ๋ฐ ๋ชจ๋ ํ ์คํธ ์ ํ์ ์ํ๋ฅผ ์ค์ (Set up)ํ๊ณ ์ ๋ฐ์ดํธ(Update)ํ๋ Methods
Writing Tests for JUnit
org.junit.jupiter.api.Assertionsclass์ Methods ์ฌ์ฉ ํ์- Javadoc์์ ์ ์ฒด ๊ธฐ๋ฅ ์ค๋ช ์ ๊ณต
- ๊ฐ Test method๋ ์กฐ๊ฑด(Assertion)์ ํ์ธํ๊ณ ํ ์คํธ ์คํจ ๋๋ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ Test runner์๊ฒ ๋ณด๊ณ ํจ.
- Test runner๋ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ณด๊ณ (Command line ๋ชจ๋)ํ๊ฑฐ๋ ๋์คํ๋ ์ด ์ ๋ฐ์ดํธ(IDE)
- ๋ชจ๋ Methods๋
void๋ฅผ ๋ฐํ org.junit.jupiter.api.Assertions์ ๋ํ์ ์ธ MethodsassertTrue(boolean)assertTrue(String, boolean)fail(String)- ...
JUnit Test Fixtures
- Test fixture๋ ํ
์คํธ์ ์ํ(state)๋ฅผ ์๋ฏธ
- ํ๋ ์ด์์ ํ ์คํธ์์ ์ฌ์ฉ๋๋ Objects ๋ฐ Variables
- ์ด๊ธฐํ (prefix values)
- ์ฌ์ค์ ๊ฐ (postfix values)
- ์๋ก ๋ค๋ฅธ ํ ์คํธ๋ ์ํ ๊ณต์ ์์ด Objects๋ฅผ ์ฌ์ฉํ ์ ์์.
- Test fixtures์์ ์ฌ์ฉ๋๋ objects๋ instance variables๋ก ์ ์ธ๋์ด์ผ ํจ.
@Beforemethod์์ ์ด๊ธฐํ๋์ด์ผ ํจ.@Aftermethod์์ ํ ๋น ํด์ ๋๋ ์ฌ์ค์ ๋ ์ ์์.
Simple JUnit Example
public class Calc
{
static public int add (int a, int b)
{
return a + b;
}
}
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalcTest
{
@Test public void testAdd()
{
assertTrue ("Calc sum incorrect",
5 == Calc.add (2, 3)); // Test values
}
}
Calcclass์CalcTestclass ์์ @Testannotation ์ฌ์ฉassertTrue๋ฅผ ์ฌ์ฉํ์ฌ ๋ง์ ๊ฒฐ๊ณผ ๊ฒ์ฆ
Testing the Min Class
import java.util.*;
public class Min
{
/**
* Returns the mininum element in a list
* @param list Comparable list of elements to search
* @return the minimum element in the list
* @throws NullPointerException if list is null or
* if any list elements are null
* @throws ClassCastException if list elements are
not mutually comparable
* @throws IllegalArgumentException if list is empty
*/
...
}
public static <T extends Comparable<? super T>> T min (List<? extends T> list)
{
if (list.size() == 0)
{
throw new IllegalArgumentException ("Min.min");
}
Iterator<? extends T> itr = list.iterator();
T result = itr.next();
if (result == null) throw new NullPointerException ("Min.min");
while (itr.hasNext())
{ // throws NPE, CCE as needed
T comp = itr.next();
if (comp.compareTo (result) < 0)
{
result = comp;
} }
return result;
}
- List์์ ์ต์ ์์๋ฅผ ๋ฐํํ๋
Minclass ์์ - Generics ์ฌ์ฉ
- ์์ธ ์ฒ๋ฆฌ (
NullPointerException,ClassCastException,IllegalArgumentException) ํฌํจ ๋ก์ง
MinTest Class
- Test fixture ๋ฐ Pre-test setup method (Prefix)
@BeforeEach: ๊ฐ Test method ์คํ ์ ํธ์ถ (setUp)
- Post test teardown method (Postfix)
@AfterEach: ๊ฐ Test method ์คํ ํ ํธ์ถ (tearDown)
- ํ์ค JUnit classes import
import static
org.junit.jupiter.api.Assertions.*;
import org.junit.Jupiter.api.*;
import java.util.*;
private List<String> list; // Test fixture
// Set up - Called before every test method.
@BeforeEach
public void setUp()
{
list = new ArrayList<String>();
}
// Tear down - Called after every test
method.
@AfterEach
public void tearDown()
{
list = null; // redundant in this example
}
Min Test Cases: NullPointerException
@Test public void testForNullList()
{
list = null;
try {
Min.min (list);
} catch (NullPointerException e) {
return;
}
fail (โNullPointerException expectedโ);
}
@Test
public void testForNullElement()
{
list.add (null);
list.add ("cat");
assertThrows(NullPointerException.class, () -> Min.min (list));
}
@Test
public void testForSoloNullElement()
{
list.add (null);
assertThrows(NullPointerException.class, () -> Min.min (list));
}
testForNullList: List๊ฐ null์ธ ๊ฒฝ์ฐ ํ ์คํธfailassertion ์ฌ์ฉ (์์ธ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉด ์คํจ ์ฒ๋ฆฌ)
testForNullElement: List ์์ ์ค null์ด ํฌํจ๋ ๊ฒฝ์ฐ ํ ์คํธassertThrows์ฌ์ฉ (์์ธ class ๋ช ์)
testForSoloNullElement: null ์์ ํ๋๋ง ์๋ ๊ฒฝ์ฐ ํ ์คํธ- ์ฝ๊ฒ ๊ฐ๊ณผ๋ ์ ์๋ ํน์ ์ผ์ด์ค ํฌ์ฐฉ
More Exception Test Cases for Min
@Test
@SuppressWarnings ("unchecked")
public void testMutuallyIncomparable()
{
List list = new ArrayList();
list.add ("cat");
list.add ("dog");
list.add (1);
assertThrows(ClassCastException.class, () -> Min.min (list));
}
@Test
public void testEmptyList()
{
assertThrows(IllegalArgumentException.class, () -> Min.min (list));
}
testMutuallyIncomparable: ๋น๊ต ๋ถ๊ฐ๋ฅํ ํ์ (String, Integer) ํผํฉ ์ClassCastExceptionํ ์คํธ- Java generics๊ฐ raw types ์ฌ์ฉ์ ๋ง์ง ์์์ ๋ณด์ฌ์ค.
testEmptyList: ๋น ๋ฆฌ์คํธ์ ๋ํIllegalArgumentExceptionํ ์คํธ
Remaining Test Cases for Min
@Test
public void testSingleElement()
{
list.add ("cat");
Object obj = Min.min (list);
assertTrue ("Single Element List", obj.equals ("cat"));
}
@Test
public void testDoubleElement()
{
list.add ("dog");
list.add ("cat");
Object obj = Min.min (list);
assertTrue ("Double Element List", obj.equals ("cat"));
}
- Happy Path ํ ์คํธ (์์ธ ์๋ ์ผ์ด์ค)
testSingleElement: ๋จ์ผ ์์ ๋ฆฌ์คํธ ํ ์คํธtestDoubleElement: ๋ ์์ ๋ฆฌ์คํธ ํ ์คํธ
Summary: Seven Tests for Min
- ์์ธ๊ฐ ์๋ 5๊ฐ์ง ํ
์คํธ
- Null list
- ์ฌ๋ฌ ์์ ์ค Null element ํฌํจ.
- Null ๋จ์ผ ์์
- ๋น๊ต ๋ถ๊ฐ๋ฅํ Types
- Empty elements
- ์์ธ๊ฐ ์๋ 2๊ฐ์ง ํ
์คํธ
6. Single element
7. Two elements
Data-Driven Tests
- ๋ฌธ์ ์ : ์ ์ฌํ ๊ฐ์ผ๋ก ํจ์๋ฅผ ์ฌ๋ฌ ๋ฒ ํ ์คํธํ ๋ ๋ฐ์ํ๋ Test code bloat(๋ถํ๋ฆฌ๊ธฐ) ๋ฐฉ์ง ํ์
- ๊ฐ๋จํ ์: ๋ ์ซ์ ๋ํ๊ธฐ
- ์ฃผ์ด์ง ์ซ์ ์์ ๋ํ๋ ๊ฒ์ ๋ค๋ฅธ ์์ ๋ํ๋ ๊ฒ๊ณผ ๋์ผํจ.
- ํ๋์ ํ ์คํธ๋ง ์์ฑํ๊ธฐ๋ฅผ ์ํจ.
- Data-driven unit tests๋ ๊ฐ Test values ์ปฌ๋ ์
์ ๋ํด ์์ฑ์๋ฅผ ํธ์ถํจ.
- ๋์ผํ ํ ์คํธ๊ฐ ๊ฐ Data values ์ธํธ์ ๋ํด ์คํ๋จ
@Parametersannotation์ด ์ง์ ๋ Method๋ก Data values ์ปฌ๋ ์ ์ ์
Example JUnit Data-Driven Unit Test
import static org.junit.jupiter.api.*;
import static org.junit.jupiter.params.provider.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import java.util.stream.Stream;
import java.util.*;
@RunWith (Parameterized.class)
public class DataDrivenCalcTest
{
private static Stream<Arguments> data() {
return Stream.of(
Arguments.of(1, 1, 2),
Arguments.of(2, 3, 5)
);
}
@ParameterizedTest
@MethodSource("data")
public void additionTest(int v1, int v2, int expected)
{ assertTrue ("Addition Test", expected == Calc.add (v1, v2)); }
}
@ParameterizedTest๋ฐ@MethodSource์ฌ์ฉ ์์ - Data source์ Test method ๋ถ๋ฆฌ
- Stream์ ํตํด Arguments(์ ๋ ฅ๊ฐ, ๊ธฐ๋๊ฐ) ์ ๋ฌ
- ๋์ผํ ๋ก์ง(
additionTest)์ผ๋ก ์ฌ๋ฌ ๋ฐ์ดํฐ ์ธํธ(1+1=2, 2+3=5) ๊ฒ์ฆ
How to Run Tests
- JUnit์ Test drivers ์ ๊ณต
- Command line์์ ์คํ๋๋ ๋ฌธ์ ๊ธฐ๋ฐ Test driver
- GUI ๊ธฐ๋ฐ Test driver (
junit.swingui.TestRunner)- Programmer๊ฐ ์คํํ Test class ์ง์ ๊ฐ๋ฅ
- "Run" ๋ฒํผ ์์ฑ
- ํ ์คํธ ์คํจ ์ JUnit์ ์คํจ ์์น ๋ฐ ๋ฐ์ํ Exceptions ์ ๋ณด ์ ๊ณต
JUnit Resources
- JUnit ๋ค์ด๋ก๋ ๋ฐ ๋ฌธ์ junit.org
- JUnit 5 User Guide
- IntelliJ ๋ธ๋ก๊ทธ์ JUnit 5 ํ ์คํธ ์์ฑ ๊ฐ์ด๋
Summary of Unit Testing
- ํ ์คํธ๋ฅผ ํจ์จ์ ์ด๊ณ ํจ๊ณผ์ ์ผ๋ก ๋ง๋๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๊ฐ๋ฅํ ๋ง์ด ์๋ํํ๋ ๊ฒ์.
- Test frameworks๋ ํ ์คํธ ์๋ํ๋ฅผ ์ํ ๋งค์ฐ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ ๊ณต
- ๊ทธ๋ฌ๋ "Silver bullet(๋ง๋ฅ ํด๊ฒฐ์ฑ )"์ ์๋. ํ ์คํธ์ ์ด๋ ค์ด ๋ฌธ์ ๋ ์ฌ์ ํ ์กด์ฌํจ.
์ด๋ค Test values๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ๊ฐ?
Test design์ ๋ฌธ์ ์ด๋ฉฐ ... Test criteria์ ๋ชฉ์
Test Suite Quality Metrics
Learning Goals
- Test suite quality metrics๋ ์ด๋ค Suite๋ฅผ ์ฌ์ฉํ ์ง ๊ฒฐ์ ํ๋ ๋ฐ ๋์์ ์ค.
- Line coverage: Suite ์คํ ์ ๋ฐฉ๋ฌธํ line์ ๋น์จ, ๋จ์ํ์ง๋ง ์ ํ๋ ํ์ ๋ง ์ค.
- Branch coverage: ์กฐ๊ฑด๋ฌธ์ True/False ๊ฐ์ ๋ชจ๋ ์๊ตฌ, ๋ ํ๋ถํจ (Data values๋ฅผ ๊ฐ์ ์ ์ผ๋ก ํตํฉ)
- Mutation analysis: Suite๊ฐ ๊ฐ์งํ Seeded defects(์ฌ์ด๋์ ๊ฒฐํจ)์ ๋น์จ ์ธก์ , ๋น์ฉ์ด ๋ง์ด ๋ค์ง๋ง ํจ๊ณผ์ ์.
Testing
- Module, Module ์งํฉ ๋๋ System ์คํ
- ๋ฏธ๋ฆฌ ๊ฒฐ์ ๋ Inputs ์ฌ์ฉ (Test case)
- ์ค์ Outputs ์บก์ฒ
- ์ค์ Outputs์ Expected outputs ๋น๊ต
- ์ค์ ๊ฒฐ๊ณผ == ์์ ๊ฒฐ๊ณผ
โ Test case ์ฑ๊ณต - ์ค์ ๊ฒฐ๊ณผ != ์์ ๊ฒฐ๊ณผ
โ Test case ์คํจ
Testing Question
- ์ธ์ ํ ์คํธ๋ฅผ ์ค๋จํด์ผ(ํ ์) ์๋๊ฐ?
- ์๋ฒฝํ์ง๋ง ์คํ ๋ถ๊ฐ๋ฅํ ๋ต: ๋ชจ๋ Test cases๋ฅผ ์คํํ์ ๋
- ์๋ฒฝํ์ง๋ง ์คํ ๋ถ๊ฐ๋ฅํ ๋ต 2: ๋ชจ๋ Faults๋ฅผ ์ฐพ์์ ๋
- ๊ฐ ์ถ๊ฐ ํ
์คํธ ์คํ์ ์๋์ ์ธ Surrogate benefit(๋๋ฆฌ ์ด์ต)์ ์ ์ ์๋๊ฐ?
- ์ค์ Fault detection ๋ฅ๋ ฅ์ ์ฌ์ ์ ์ ํํ ์ธก์ ํ ์ ์์ผ๋ฏ๋ก Surrogate(๋๋ฆฌ) ์งํ ์ฌ์ฉ
- ์ ๋ขฐํ ์ ์๋ Surrogate measure๋ ๋งค์ฐ ์ ์ฉํจ.
- ๋ Test cases๋ฅผ ๋น๊ตํ์ฌ ์ด๋ค ๊ฒ์ ์ฌ์ฉํ ์ง ๊ฒฐ์ ๊ฐ๋ฅ
- ์ธก์ ์ ์ฑ๊ฒฉ์ ๋ฐ๋ผ ์ค๋จ ์์ (๋ถ์์ ํ์ง๋ง ์ค์ง์ ์ผ๋ก ํ์ํ)์ ํ์ํ ์ ์์.
Coverage
- Test suite๊ฐ ๋ชจ๋ Requirements๋ฅผ ์ปค๋ฒ("checked")ํ๊ธฐ๋ฅผ ์ํจ.
- X coverage๋ X๊ฐ Test suite์ ์ํด ์คํ/ํ์ฌ๋๋ ์ ๋
- ์์
- Code coverage: Source code๊ฐ Test suite์ ์ํด ์คํ๋๋ ์ ๋
- Statement coverage: ์คํ๋ Source statements์ ๋น์จ
Do Tests Cover All Requirements?
- ์ด์์ ์ธ ์ธ๊ณ์์๋ requirements์ test cases ๊ฐ์ Traceability(์ถ์ ์ฑ)๊ฐ ์กด์ฌ
- ์ฆ, ๊ฐ ํ
์คํธ ์ผ์ด์ค์๋ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์์ด ์ฒจ๋ถ๋จ
- "์ด ํ ์คํธ๋ฅผ ํต๊ณผํ ํ๋ก๊ทธ๋จ์ ์๊ตฌ์ฌํญ X๋ฅผ ๋ง์กฑํจ"
- "์ด ํ ์คํธ ํต๊ณผ ์ ํ๋ก๊ทธ๋จ์ด ์๊ตฌ์ฌํญ Y๋ฅผ ์ค์ํ๋ค๋ ํ์ ์ ์ค"
- ํญ๊ณต์ฐ์ฃผ ๋ฑ ํน์ ์ฐ์ ์ ์ ์ธํ๊ณ ๊ณต์์ ์ธ Traceability๋ ๋๋ฌพ
An Approximation
- Requirements์ ๋ํ ๊ณต์์ ์ธ Traceability๊ฐ ์๋ค๊ณ ๊ฐ์
- ๋ฐ๋ผ์ ํ๋ก๊ทธ๋จ์ด ์๊ตฌ๋๋ ๋ชจ๋ ์ข์ ์ผ๋ง ์ํํ๋ค๊ณ ํ ์คํธํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅ(๋๋ ์คํ ๋ถ๊ฐ๋ฅ)
Donโt Do Bad Things
- ์ ์ด๋ ํ๋ก๊ทธ๋จ์ด ํน์ "๋์ ์ผ"์ ํ์ง ์๋๋ค๋ ๊ฒ์ ํ
์คํธํ ์ ์์.
- ์: Segfault ๋ฐ์ ์ ํจ, ์ํธ ์ ์ถ ์ ํจ, ํน์ ์ ๋ ฅ์ ๋ํด ์ค๋ต ๋ด์ง ์์.
- "๋์ ์ผ์ ์ ๋ ํ์ง ์์"์ "ํญ์/๊ฒฐ๊ตญ ์ข์ ์ผ์ ํจ"๊ณผ ๋์ผํ์ง ์์.
- Liveness vs. Safety properties
Testing to Find Bugs
- ํ๋ก๊ทธ๋จ์ด "๋์ ์ผ"์ ํ์ง ์๋๋ค๋ ํ์ ์ ์ป๊ธฐ ์ํด ํ ์คํธํจ.
- ์ฆ, ๋ฒ๊ทธ๊ฐ ์๋ค๋ ํ์
- ํต์ฌ ๋ ผ๋ฆฌ์ ๊ด์ฐฐ: Line X๋ฅผ ์ ๋ ํ ์คํธํ์ง ์์ผ๋ฉด, Line X์ Bug๊ฐ ์กด์ฌํ์ง ์๋๋ค๋ ๊ฒ์ ํ ์คํธ๋ก ๋ฐฐ์ ํ ์ ์์.
"X๋ฅผ ์ปค๋ฒํ๋ ํ ์คํธ ์์ โ X์ ๋ฒ๊ทธ๊ฐ ์์ ์ ์์"
- Line X๋ฅผ ํ
์คํธํด๋ ์ฌ์ ํ Line X์ ๋ฒ๊ทธ๊ฐ ์์ ์ ์์.
- ์:
foo(a,b) { return a/b; }์์foo(6,2)ํ ์คํธ ์ ์ฑ๊ณตํ์ง๋ง0์ผ๋ก ๋๋ ๋ ๋ฒ๊ทธ ์กด์ฌ ๊ฐ๋ฅ
- ์:
- ๊ทธ๋ฌ๋ X๋ฅผ ํ
์คํธํ๋ ๊ฒ์ X์ ์ ํ์ฑ์ ๋ํด ์์ง๋ง
0์ด ์๋ ํ์ ์ ์ค.
โAll Other Things Being Equalโ
- Test A๊ฐ line 1, 2๋ฅผ ๋ฐฉ๋ฌธํ๊ณ , Test B๊ฐ line 1, 2, 3, 4๋ฅผ ๋ฐฉ๋ฌธํ๋ค๋ฉด,
- ๋ค๋ฅธ ๋ชจ๋ ์กฐ๊ฑด์ด ๋์ผํ ๋ Test B๋ฅผ ์ ํธํจ.
- Test A๋ 1, 2์ ๋ํ ํ์ ๋ง ์ฃผ๊ณ 3, 4์ ๋ํ ์ ๋ณด๋ ์์.
- Test B๋ 1, 2, 3, 4์ ๋ํ ํ์ ์ ์ค.
- ํ
์คํธ๋ line๋น ์ป๋ ํ์ /์ ๋ณด๊ฐ ์ด๋ผ๋ฉด, Test A๋ , Test B๋ ๋ฅผ ์ ๊ณต ()
- , ์ด๋ฏ๋ก
Simplifying Assumptions
- ๊ฐ์ 1: ๋ฐฉ๋ฌธํ ๊ฐ line์ ๋ํด ๋์ผํ ์์ ํ์ (๋๋ ์ ๋ณด)์ ์ป์.
- ๊ฐ์ 2: ๋ฐฉ๋ฌธํ line๋น ์ป๋ ํ์ (๋๋ ์ ๋ณด)์ ์์ ์์์.
Using Line Coverage
- ๋ฆฌ์์ค ์์ฐ("AOTBE", etc) ๋ด์์ ์คํ๋๋ ๋ Test suites๊ฐ ์์ ๋, ํ๋๋ง ์คํํ ์ ์๋ค๋ฉด Line coverage๊ฐ ๋ ๋์ ๊ฒ์ ์ ํธํจ.
- Coverage๋ ๋ Test suites๋ฅผ ๋น๊ตํ๊ณ "๋ ๋์" ๊ฒ์ ์ ํํ๊ฒ ํด์ฃผ๋ Metric
- ์ด ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ Software process์ ์์ฌ ๊ฒฐ์ ("ํ ์คํธ๋ฅผ ์ด๋ป๊ฒ ํด์ผ ํ๋๊ฐ?")์ ์๋ดํจ.
Collecting Line Coverage
- ๊ฐ์ฅ ๊ฐ๋จํ๊ฒ๋ Print-statement debugging ๋ฐฉ์
- ํ๋ก๊ทธ๋จ์ ๋ชจ๋ line ์์ ์ถ๋ ฅ๋ฌธ ์ฝ์
- ๋ชจ๋ ํ ์คํธ ์คํ, ์ถ๋ ฅ ์ ๋ณด ์์ง, ์ค๋ณต ์ ๊ฑฐ, ์นด์ดํธ
- ์ค์ง์ ์ฐ๋ ค: Observer effect (๊ด์ฐฐ์ด ํ์์ ๋ณํ์ํด)
Coverage Instrumentation
- Coverage instrumentation์ Observer effect๋ฅผ ์ต์ํํ๋ ๋ฐฉ์์ผ๋ก Coverage ์ ๋ณด๋ฅผ ๊ธฐ๋กํ๋๋ก ํ๋ก๊ทธ๋จ์ ์์ ํจ.
- Source ๋๋ Binary ๋ ๋ฒจ์์ ์ํ ๊ฐ๋ฅ
- ์ค์ ๋ก stdout/stderr์ ์ถ๋ ฅํ์ง ์์.
- ์๋๋ฅผ ๋๋ฌด ๋๋ฆฌ๊ฒ ํ์ง ์์ (์ค๋ณต ์ถ๋ ฅ ์ ํ์ธ?)
- Infinite loops๋ฅผ ๋์ ํ์ง ์์ ("print"๋ฅผ "print" ํธ์ถ๋ก ๊ณ์ธก?)
Good News: โSolvedโ Problem
- ์ ์ฐ๊ตฌ๋ ๋ฌธ์ ์ด๋ฉฐ ๋ค์ํ ํํ์ Coverage์ ๋ํ Push-button ์๋ฃจ์
์ด ์กด์ฌํจ.
- IDE ๋ด์ฅ ๋๋ ์ธ๋ถ ๋๊ตฌ
- ์: Python์ coverage,
gcc์gcov, Java์cobertura๋ฑ
Problems with Line Coverage
- Line coverage์ ๋ฌธ์ ์ ์ ๋ฌด์์ธ๊ฐ?
- 100% Line coverage ์ํฉ์์๋ ํ๋ก๊ทธ๋จ์ ์ฌ์ ํ ๋ฒ๊ทธ๊ฐ ์์ ์ ์๋๊ฐ?
- (์ฌ๊ฒํ ) Line X๋ฅผ ํ ์คํธํด๋ ์ฌ์ ํ Line X์ ๋ฒ๊ทธ๊ฐ ์์ ์ ์์.
Data Values and Implicit Control Flow

Intuition
- ๋ง์ ํฅ๋ฏธ๋ก์ด Data values๋ Implicit ๋๋ Explicit ์ ์ด ๋ณ๊ฒฝ์ ์ ๋ฐํจ.
- ์ฆ, Conditionals์ ๋ค๋ฅธ ๋ถ๊ธฐ๊ฐ ์คํ๋๋๋ก ํจ.
- ๋น๊ณต์์ ์ผ๋ก, ํฅ๋ฏธ๋ก์ด Data values๋ฅผ ์ปค๋ฒํ๋ ๋ฌธ์ ๋ ๋ชจ๋ Conditionals ๋ถ๊ธฐ๋ฅผ ์ปค๋ฒํ๋ ๋ฌธ์ ๋ก ๊ท๊ฒฐ๋ ์ ์์.
Branch Coverage
- Branch coverage๋ Test suite์ ์ํด ์คํ๋ Conditional branches์ ์ด์๋ฅผ ๊ณ์ฐํ๋ Test suite quality metric (if->true์ if->false๋ฅผ ๋ณ๋๋ก ๊ณ์ฐ)
- Branch coverage๋ Line coverage๋ฅผ ํฌํจ(Subsume)ํ ์ ์์.
- ๋ชจ๋ Branches๋ฅผ ์ปค๋ฒํ๋ Test suite๋ ๋ชจ๋ Lines๋ ์ปค๋ฒํจ.
Branch vs. Line
- Branch coverage๋ ์ผ๋ฐ์ ์ผ๋ก Line coverage๋ณด๋ค ๋ ๋ง์ ํ์ ์ ์ค.
- ์ผ๋ฐ์ ์ผ๋ก 100% Branch coverage๋ 100% Line coverage๋ฅผ ์๋ฏธํจ.
- ๊ทธ๋ฌ๋ Branch coverage๋ ๋์ Line coverage๋ฅผ ๋ฌ์ฑํ๋ ๊ฒ๋ณด๋ค ๋์ Branch coverage๋ฅผ ๋ฌ์ฑํ๊ธฐ ์ด๋ ต๋ค๋ ์ ์์ "๋ ๋น์"
- ์ฐธ๊ณ : Quality๊ฐ ์ค์ ๋ก "๋ ๋น์ผ" ๊ฒ์ด ์๋๋ผ, ์ด์ ์ Line coverage๋ง์ผ๋ก ์ถฉ๋ถํ๋ค๊ณ ์ค์ค๋ก ์์๋ ๊ฒ์. ์ ํํ ๊ฒ์ ์๋ ๋น์ฉ์ด ๋ฆ.
Other Flavors
- Function Coverage: ํธ์ถ๋ Functions์ ๋น์จ
- Condition Coverage: Boolean subexpressions๊ฐ True์ False๋ก ํ๊ฐ๋ ๋น์จ
- Modified Condition / Decision Coverage (MC/DC): Function coverage + Branch coverage (๋จ์ํ๋ ์ค๋ช
)
- Mission critical (์: ํญ๊ณต ์ ์) Software์์ ์ฌ์ฉ๋จ
Mutation Testing
- Mutation testing (๋๋ Mutation analysis)์ Test suite์ ํ์ง์ด ์๋์ ์ผ๋ก ์ถ๊ฐ๋ Defects๋ฅผ ์ฐพ๋ ์์ ๊ด๋ จ๋ Test suite adequacy metric
- ๋น๊ณต์์ ์ค๋ช : "Test suite๊ฐ ๋ณด์ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๋ฐ ์ ๋ง ํ๋ฅญํ๋ค๊ณ ? ์์ค ์ฝ๋์ ์๋์ ์ผ๋ก ๋ฒ๊ทธ๋ฅผ ์ถ๊ฐํด์ ์ฐพ๋์ง ๋ด์ผ๊ฒ ์ด!"
Defect Seeding
- Defect seeding์ ํ๋ก๊ทธ๋จ์ ์๋์ ์ผ๋ก Defect๋ฅผ ๋์
ํ๋ ๊ณผ์
- ๋์ ๋ Defect๋ ์ค์ ๊ฐ๋ฐ์๊ฐ ๋์ ํ๋ Defects์ ์๋์ ์ผ๋ก ์ ์ฌํจ.
- Seeding์ ์ผ๋ฐ์ ์ผ๋ก Source code๋ฅผ ๋ณ๊ฒฝํ์ฌ ์ํ๋จ
- Mutation testing์ ๊ฒฝ์ฐ Defect seeding์ ์ผ๋ฐ์ ์ผ๋ก ์๋์ผ๋ก ์ํ๋จ (์ธ๊ฐ์ ๋ฒ๊ทธ ๋ชจ๋ธ ๊ธฐ๋ฐ)
Mutation Operators
- Mutation operator๋ ํ๋ก๊ทธ๋จ ์ง์ ์ ์ฒด๊ณ์ ์ผ๋ก ๋ณ๊ฒฝํจ.
- Mutation testing์์ mutation operators๋ ์ญ์ฌ์ ์ธ ์ธ๊ฐ์ Defects๋ฅผ ๋ชจ๋ธ๋ก ํจ.

Mutant
- Mutant (๋๋ Variant)๋ ํ๋ ์ด์์ ํ๋ก๊ทธ๋จ ์์น์ ํ๋ ์ด์์ Mutation operators๋ฅผ ์ ์ฉํ์ฌ ์์ฑ๋ ์๋ณธ ํ๋ก๊ทธ๋จ์ ๋ฒ์
- Mutant์ Order๋ ์ ์ฉ๋ Mutation operators์ ์

Competent Programmers
- Competent programmer hypothesis: ํ๋ก๊ทธ๋จ Faults๋ ๊ตฌ๋ฌธ์ ์ผ๋ก ์์ผ๋ฉฐ ๋ช ๋ฒ์ ํค์คํธ๋กํฌ๋ก ์์ ํ ์ ์๋ค๋ ๊ฐ์ค
- ํ๋ก๊ทธ๋๋จธ๋ ๋์ฒด๋ก ์ฌ๋ฐ๋ฅธ ํ๋ก๊ทธ๋จ์ ์์ฑํจ.
- ๋ฐ๋ผ์ mutants๋ ์ค์ Faults์ ๊ฐ๋ฅ์ฑ ์๋ ํจ๊ณผ๋ฅผ ์๋ฎฌ๋ ์ด์ ํจ.
- ๋ฐ๋ผ์ Test suite๊ฐ ์ธ์์ ์ธ Mutants๋ฅผ ์ ํฌ์ฐฉํ๋ค๋ฉด, ํ๋ก๊ทธ๋จ์ ์๋ ค์ง์ง ์์ ์ค์ Faults๋ ์ ํฌ์ฐฉํ ๊ฒ์.
Competent? Really?
- Competent programmer hypothesis๊ฐ ์ฌ์ค์ธ๊ฐ?
- ์ ๊ทธ๋ฆฌ๊ณ ์๋์ค
- ์ธ๊ฐ์ด ๋จ์ํ ์คํ(์: +๋ฅผ -๋ก)๋ฅผ ์์ฃผ ๋ด๋ ๊ฒ์ ์ฌ์ค์.
- ๊ทธ๋ฌ๋ ์ผ๋ถ ๋ฒ๊ทธ๋ ๊ทธ๋ณด๋ค ๋ ๋ณต์กํ ๊ฒ๋ ์ฌ์ค์.
Coupling Effect
- Coupling effect hypothesis: ๋ณต์กํ faults๋ ๋จ์ํ faults์ ๊ฒฐํฉ(Coupled)๋์ด ์์ด, ํ๋ก๊ทธ๋จ์ ๋ชจ๋ ๋จ์ํ faults๋ฅผ ๊ฐ์งํ๋ Test suite๊ฐ ๋์ ๋น์จ์ ๋ณต์กํ faults๋ ๊ฐ์งํ ๊ฒ์ด๋ผ๋ ๊ฐ์ค
- ์ฌ์ค์ธ๊ฐ?
- ๋จ์ํ Mutants๋ฅผ ๊ฐ์งํ๋ ํ ์คํธ๋ ์ญ์ฌ์ ์ผ๋ก 2์ฐจ ๋ฐ 3์ฐจ Order mutants์ 99% ์ด์์ ๊ฐ์งํ ์ ์์์ [A. J. Offutt ์ฐ๊ตฌ]
Mutation Testing
- Test suite๊ฐ ์๋ณธ์ ํต๊ณผํ์ง๋ง Mutant๋ ์คํจํ๊ฒ ๋ง๋ค๋ฉด, ํด๋น Mutant๋ฅผ kill(๊ฐ์ง, ๋๋ฌ๋)ํ๋ค๊ณ ํจ.
- Test suite์ Mutation testing (๋๋ Analysis)์ ๋ค์์ Mutants๋ฅผ ๋ง๋ค๊ณ ๊ทธ์ค kill๋ ๋น์จ์ ์ธก์ ํ์ฌ ์งํ๋จ
- ์ด ๋น์จ์ Mutation adequacy score (๋๋ Mutation score)๋ผ๊ณ ํจ.
- ์ ์๊ฐ ๋์ Test suite๊ฐ ๋ ์ข์.
Mutation Analysis: Pros and Cons
- ๋ค๋ฅธ Test suite adequacy criteria๋ฅผ ํฌํจ(Subsume)ํ ์ ์ฌ๋ ฅ์ด ์์ (๋งค์ฐ ์ข์ ์ ์์)
- ์ด๋ค Mutation operators๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ๊ฐ?
- ์ด๋์ ์ ์ฉํ๊ณ ์ผ๋ง๋ ์์ฃผ ์ ์ฉํ ๊ฒ์ธ๊ฐ? (๋ณดํต ๋ฌด์์์ง๋ง ๋ฐฉ๋ฒ์ด ๋ฌธ์ )
- It is very expensive. 1,000๊ฐ์ Mutants๋ฅผ ๋ง๋ค๋ฉด Test suite๋ฅผ 1,000๋ฒ ์คํํด์ผ ํจ!
Equivalent Mutant Problem
x = a + b; y = c + d;๊ฐ ์์ ๋ ๋ ๋ฌธ์ฅ์ ๋ฐ๊พธ๋ ๊ฒฝ์ฐ๋ฅผ ๊ฐ์ - ๊ฒฐ๊ณผ ํ๋ก๊ทธ๋จ์ mutant์ด์ง๋ง ์๋ฏธ์ ์ผ๋ก๋ ์๋ณธ๊ณผ ๋์ผ (Semantically equivalent)
- ์๋ณธ์ด ํต๊ณผ/์คํจํ๋ ๋ชจ๋ ํ ์คํธ๋ฅผ ๋์ผํ๊ฒ ํต๊ณผ/์คํจํจ.
- ๋ฐ๋ผ์ mutation score๋ฅผ ํฌ์์ํด
- Equivalent mutants๋ฅผ ๊ฐ์งํ๋ ๊ฒ์ ํฐ ๋ฌธ์ ์. ์ผ๋ง๋ ์ด๋ ค์ธ๊น?
- Undecidable (๊ฒฐ์ ๋ถ๊ฐ๋ฅ) ๋ฌธ์ ์ ...

