F - Fast (λΉ λ¦): ν μ€νΈλ λΉ λ₯΄κ² μ€νλμ΄μΌ νλ€.
I - Independent/Isolated (λ 립μ /격리λ): κ° ν μ€νΈλ μλ‘ λ 립μ μ΄μ΄μΌ νλ©°, λ€λ₯Έ ν μ€νΈμ 곡μ μνλ₯Ό κ°μ§μ§ μμμΌ νλ€.
R - Repeatable (λ°λ³΅ κ°λ₯): ν μ€νΈλ μ΄λ€ νκ²½μμλ λ°λ³΅ κ°λ₯ν΄μΌ νλ€.
S - Self-Validating (μ체 κ²μ¦ κ°λ₯): ν μ€νΈλ μμ κ²°κ³Όλ₯Ό μ€μ€λ‘ κ²μ¦ν μ μμ΄μΌ νλ©°, μλ κ²μ¬λ₯Ό μꡬνμ§ μμμΌ νλ€.
T - Timely (μ μμ): ν μ€νΈλ μ μ ν μκΈ°μ μμ±λμ΄μΌ νλ€. μΌλ°μ μΌλ‘ ν μ€νΈ μ½λλ μ€μ μ½λλ₯Ό μμ±νκΈ° μ μ΄λ λμμ μμ±λμ΄μΌ νλ€.
μΉ μλΉμ€μ λ‘κ·ΈμΈ κΈ°λ₯μ ν μ€νΈνλ κ²½μ°, μ€μ λ°μ΄ν°λ² μ΄μ€λ μΈλΆ μμ€ν νΈμΆ λμ μ Mock κ°μ²΄λ μΈ-λ©λͺ¨λ¦¬ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©ν¨μΌλ‘μ¨ ν μ€νΈ μλλ₯Ό κ°μ νλ€.
const { AuthenticationService, UserRepository } = require('./myservice');
describe('FastLoginTest', () => {
test('test login with mock', () => {
// UserRepositoryμ Mock κ°μ²΄λ₯Ό μμ±ν¨
const mockUserRepo = {
validateUser: jest.fn()
};
// Mock κ°μ²΄κ° νμ Trueλ₯Ό λ°ννλλ‘ μ€μ ν¨
mockUserRepo.validateUser.mockReturnValue(true);
// AuthenticationService μΈμ€ν΄μ€λ₯Ό Mock UserRepositoryμ ν¨κ» μμ±ν¨
const authService = new AuthenticationService(mockUserRepo);
// λ‘κ·ΈμΈ ν¨μκ° μμλλ‘ μλνλμ§ κ²μ¦ν¨
expect(authService.login('username', 'password')).toBeTruthy();
});
});
validate_user
λ©μλκ° νΈμΆλ λ νμ True
λ₯Ό λ°ννλλ‘ μ€μ λμλ€. μ΄λ° λ°©μμ ν
μ€νΈ μλλ₯Ό λν ν₯μμν¨λ€.κ° λ¨μ ν μ€νΈλ λ€λ₯Έ ν μ€νΈμ κ²°κ³Όλ μνμ μν₯μ λ°μ§ μκ³ λ 립μ μΌλ‘ μ€νλμ΄μΌ νλ€. μλ₯Ό λ€μ΄, μ¬μ©μ κ΄λ¦¬ μμ€ν μμ ν ν μ€νΈκ° μ¬μ©μλ₯Ό μΆκ°νλ κ²½μ°, λ€λ₯Έ ν μ€νΈμμλ μ΄ μΆκ°λ μ¬μ©μμ μμ‘΄ν΄μλ μ λλ€.
const { UserService } = require('./UserService');
describe('IndependentUserTests', () => {
let userService;
// κ° ν
μ€νΈ μ μ userServiceλ₯Ό μλ‘ μ΄κΈ°ννμ¬ κ° ν
μ€νΈκ° λ
립μ μΌλ‘ μ€νλ¨
beforeEach(() => {
userService = new UserService();
});
// μλ‘μ΄ μ¬μ©μ μΆκ° κΈ°λ₯μ ν
μ€νΈ
test('test add user', () => {
userService.addUser("newuser1");
expect(userService.userExists("newuser1")).toBeTruthy();
});
// μ¬μ©μ μ κ±° κΈ°λ₯μ ν
μ€νΈ
test('test remove user', () => {
userService.addUser("temporaryuser");
userService.removeUser("temporaryuser");
expect(userService.userExists("temporaryuser")).toBeFalsy();
});
});
beforeEach
λ κ° ν
μ€νΈκ° μμνκΈ° μ μ userService
μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννλ€. μ΄λ κ² νλ©΄ κ°κ°μ ν
μ€νΈκ° μλ‘ λ
립μ μΌλ‘ μ€νλλ€. 첫 λ²μ§Έ ν
μ€νΈ('test add user')λ μ¬μ©μ μΆκ° κΈ°λ₯μ, λ λ²μ§Έ ν
μ€νΈ('test remove user')λ μ¬μ©μ μ κ±° κΈ°λ₯μ ν
μ€νΈνλ€. μ΄ λ°©μμ ν΅ν΄ κ° ν
μ€νΈλ λ€λ₯Έ ν
μ€νΈμ μ€ν μνλ κ²°κ³Όμ μν₯μ λ°μ§ μμΌλ©° λ
립μ μΌλ‘ μνλλ€.ν μ€νΈ μΌμ΄μ€λ μ€μ€λ‘ κ²°κ³Όκ° μ¬λ°λ₯Έμ§λ₯Ό νλ¨ν μ μμ΄μΌ νλ€. μλ₯Ό λ€μ΄, νμΌμμ νΉμ λ°μ΄ν°λ₯Ό μ½λ κΈ°λ₯μ ν μ€νΈν λ, ν μ€νΈ μ½λλ μμλλ κ²°κ³Ό κ°μ κ°μ§κ³ μ€μ κ²°κ³Όμ μλμΌλ‘ λΉκ΅ν΄μΌ νλ€. μλμΌλ‘ κ²°κ³Όλ₯Ό νμΈν νμκ° μμ΄μΌ νλ€.
const { DataProcessor } = require('./DataProcessor');
describe('SelfValidatingTest', () => {
test('data reading from file', () => {
const processor = new DataProcessor();
const expectedOutput = { name: "John", age: 30 };
expect(processor.readDataFromFile("user_data.txt")).toEqual(expectedOutput);
});
});
readDataFromFile
λ©μλλ₯Ό μ¬μ©νμ¬ user_data.txt
νμΌμμ λ°μ΄ν°λ₯Ό μ½λλ€. ν
μ€νΈλ μ½μ λ°μ΄ν°κ° μμλλ κ²°κ³ΌμΈ { name: "John", age: 30 }
μ κ°μμ§λ₯Ό μλμΌλ‘ κ²μ¦νλ€. κ²°κ³Ό νμΈμ΄ μλνλμ΄ μκΈ° λλ¬Έμ κ°λ°μλ λ§€λ² μλμΌλ‘ κ²°κ³Όλ₯Ό κ²μ¬ν νμκ° μλ€. μ΄λ κ² μλ κ²μ¦μ νλ ν
μ€νΈλ μ€λ₯ κ°λ₯μ±μ μ€μ΄κ³ , ν
μ€νΈ κ³Όμ μ ν¨μ¨μ±μ λμ¬μ€λ€.ν μ€νΈλ μ μ ν μκΈ°μ μμ±λμ΄μΌ νλ€. μ΄λ λ³΄ν΅ ν μ€νΈ λμ κΈ°λ₯μ΄ κ°λ°λκΈ° λ°λ‘ μ μ μλ―Ένλ€. μλ₯Ό λ€μ΄, μλ‘μ΄ κΈ°λ₯μ κ°λ°νκΈ° μ μ κ·Έ κΈ°λ₯μ κ²μ¦ν ν μ€νΈλ₯Ό λ¨Όμ μμ±νλ κ²μ λ§νλ€. μ΄ λ°©μμ ν μ€νΈ μ£Όλ κ°λ°(Test-Driven Development, TDD)μ ν΅μ¬ μμΉ μ€ νλμ΄λ€.
import unittest
from my_app import new_feature_function
class TimelyTest(unittest.TestCase):
def test_new_feature(self):
# μμ§ κ΅¬νλμ§ μμ μλ‘μ΄ κΈ°λ₯μ ν
μ€νΈνλ€.
# ν
μ€νΈκ° μ€ν¨νλ κ²μ ꡬνλμ§ μμκΈ° λλ¬Έμ΄λ€.
self.assertEqual(new_feature_function(), expected_result)
if __name__ == "__main__":
unittest.main()
new_feature_function
μ μμ§ κ΅¬νλμ§ μμλ€. μ°λ¦¬λ λ¨Όμ μ΄ κΈ°λ₯μ λν ν
μ€νΈλ₯Ό μμ±νκ³ , κ·Έ λ€μμ μ€μ κΈ°λ₯μ ꡬννλ€. μ΄λ κ² ν
μ€νΈλ₯Ό λ¨Όμ μμ±νλ©΄ μ€κ³μ λ¬Έμ λ₯Ό μ‘°κΈ°μ λ°κ²¬νκ³ , μΆν μ½λλ₯Ό 리ν©ν λ§ν λ μ€μλ₯Ό μ€μΌ μ μλ μ΄μ μ΄ μλ€. λν, κΈ°λ₯μ΄ μ¬λ°λ₯΄κ² μλνλμ§ νμΈν μ μλ μλ κ²μ¦ μλ¨μ 미리 κ°μΆκ² λλ€.