User Tools

Site Tools


tanszek:oktatas:tdd_es_bdd

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tanszek:oktatas:tdd_es_bdd [2024/10/12 11:09] – [3. Mappastruktúra létrehozása] kneheztanszek:oktatas:tdd_es_bdd [2025/03/03 09:55] (current) – [9. BDD stílusú tesztek] knehez
Line 74: Line 74:
 ni ./repositories/userRepository.js ni ./repositories/userRepository.js
 </sxh> </sxh>
-megjegyzés: az ''ni'' parancs powershell-ben a linuxos ''touch'' parancs megfelelője.+//megjegyzés//: az ''ni'' parancs powershell-ben a linuxos ''touch'' parancs megfelelője.
  
 Most a projekt struktúrája így néz majd ki: Most a projekt struktúrája így néz majd ki:
Line 93: Line 93:
 </code> </code>
  
 +Létrejött három üres állomány.
 ==== 4. Mocha konfigurálása ==== ==== 4. Mocha konfigurálása ====
  
-A **Mocha** futtatásához a `package.jsonfájlban hozzá kell adni egy részt, amely a `mochaparancsot futtatja a `testmappában:+A **Mocha** futtatásához a ''package.json'' fájlban hozzá kell adni egy részt, amely a ''mocha'' parancsot futtatja a ''test'' mappában:
  
-Nyissuk meg a `package.jsonfájlt, és addjuk hozzá a `scriptsrészhez a következőt:+Nyissuk meg a ''package.json'' fájlt, és addjuk hozzá a ''scripts'' részhez a következőt:
  
-```json+<sxh json
 +"type": "module",
 "scripts": { "scripts": {
   "test": "mocha"   "test": "mocha"
 } }
-```+</sxh>
  
 ==== 5. Tesztek írása (TDD módszerrel) ==== ==== 5. Tesztek írása (TDD módszerrel) ====
  
-Most kezdhetjük a TDD folyamatot: először a teszteket írdjuk meg. Például a ''userService.test.js'' fájlba írjuk a következő teszteket:+Most kezdhetjük a TDD folyamatot: először a teszteket írdjuk meg. Például a ''userRepository.test.js'' fájlba írjuk a következő teszteket:
  
 <sxh javascript> <sxh javascript>
-const assert = require('assert')+import assert from 'assert'; 
-const sinon = require('sinon'); +import UserRepository from '../repositories/userRepository.js';
-const bcrypt = require('bcrypt'); +
-const UserRepository = require('../repositories/userRepository'); +
-const UserService = require('../services/userService');+
  
-describe('UserService', function() {+describe('UserRepository', function() {
      
-  let userService; +  let userRepository;
-  let userRepositoryStub;+
  
   beforeEach(function() {   beforeEach(function() {
-    userRepositoryStub sinon.stub(UserRepository.prototype, 'findUserByEmail'); +    userRepository = new UserRepository();
-    userService = new UserService(new UserRepository());+
   });   });
  
-  afterEach(function() { +  it('should return null if user is not found by email', async function() { 
-    sinon.restore();+    const user = await userRepository.findUserByEmail('notfound@example.com'); 
 +    assert.strictEqual(user, null);
   });   });
  
-  it('should return error if email is already in use', async function() { +  it('should save a user and retrieve it by email', async function() { 
-    userRepositoryStub.resolves({ email: 'existing@example.com' }); +    const newUser = { email: 'test@example.com', password: 'hashedPassword' }
- +    await userRepository.saveUser(newUser); 
-    const result = await userService.registerUser('existing@example.com', 'password123'); +     
-    assert.strictEqual(result.successfalse); +    const foundUser = await userRepository.findUserByEmail('test@example.com'); 
-    assert.strictEqual(result.message, 'Email already in use');+    assert.strictEqual(foundUser.email'test@example.com'); 
 +    assert.strictEqual(foundUser.password, 'hashedPassword');
   });   });
  
-  it('should hash the password and register user if email is not taken', async function() { +  it('should handle saving multiple users', async function() { 
-    userRepositoryStub.resolves(null); +    const user1 = { email: 'user1@example.com', password: 'password1' }
-     +    const user2 { email: 'user2@example.com'password: 'password2}; 
-    const bcryptStub sinon.stub(bcrypt, 'hash').resolves('hashedPassword'); + 
-     +    await userRepository.saveUser(user1); 
-    const result = await userService.registerUser('newuser@example.com', 'plainPassword'); +    await userRepository.saveUser(user2); 
-     + 
-    assert.strictEqual(bcryptStub.calledOnce, true); +    const foundUser1 = await userRepository.findUserByEmail('user1@example.com'); 
-    assert.strictEqual(bcryptStub.calledWith('plainPassword'), true); +    const foundUser2 = await userRepository.findUserByEmail('user2@example.com'); 
-    assert.strictEqual(result.successtrue); + 
-    assert.strictEqual(result.message, 'User registered successfully');+    assert.strictEqual(foundUser1.email, 'user1@example.com'); 
 +    assert.strictEqual(foundUser2.email'user2@example.com');
   });   });
 }); });
Line 157: Line 157:
 Futtasd a Mocha teszteket, hogy megbizonyosodj arról, hogy a tesztek elbuknak (mivel még nem írtad meg a tényleges implementációt). Futtasd a Mocha teszteket, hogy megbizonyosodj arról, hogy a tesztek elbuknak (mivel még nem írtad meg a tényleges implementációt).
  
-```bash+<sxh bash>
 npm test npm test
-```+</sxh>
  
-Ez a parancs futtatja a `mochaparancsot, amely végigmegy a `testmappában lévő teszteken. Mivel a `UserService` és `UserRepositorymég nem implementált, a tesztek elbuknak, ami a TDD módszer lényege: először a tesztek buknak el, majd az implementáció következik.+Ez a parancs futtatja a ''mocha'' parancsot, amely végigmegy a ''test'' mappában lévő teszteken. Mivel a ''UserRepository'' még nem implementált, a tesztek elbuknak, ami a TDD módszer lényege: először a tesztek buknak el, majd az implementáció következik.
  
-### 7. **Implementáció megírása**+{{:tanszek:oktatas:pasted:20241012-113656.png}} 
 + 
 +==== 7. Implementáció megírása ====
  
 Most írd meg a tényleges kódot a tesztek sikeressé tételéhez. Most írd meg a tényleges kódot a tesztek sikeressé tételéhez.
  
-#### `userRepository.js`:+''userRepository.js'':
  
-```javascript+<sxh javascript>
 // repositories/userRepository.js // repositories/userRepository.js
  
Line 190: Line 192:
 } }
  
-module.exports = UserRepository; +export default UserRepository; 
-```+</sxh>
  
-#### `userService.js`:+==== 8Tesztek újrafuttatása ====
  
-```javascript +Most futtassuk újra a teszteket:
-// services/userService.js+
  
-const bcrypt = require('bcrypt');+<code> 
 +npm test 
 +</code> 
 + 
 +Most a teszteknek sikeresen át kell menniük, mivel az implementáció megfelel a tesztek elvárásainak. 
 + 
 +{{:tanszek:oktatas:pasted:20241012-113731.png}} 
 + 
 + 
 +==== 9. BDD stílusú tesztek ==== 
 + 
 +Hozzuk létre a ''test/userRepository.test.js''-t az alábbi tartalommal. 
 + 
 +<sxh javascript> 
 +import { expect } from 'chai'; 
 +import sinon from 'sinon'; 
 +import bcrypt from 'bcrypt'; 
 +import UserRepository from '../repositories/userRepository.js'; 
 +import UserService from '../services/userService.js'; 
 + 
 +describe('UserService', function() { 
 +   
 +  let userService; 
 +  let userRepositoryStub; 
 + 
 +  beforeEach(function() { 
 +    // Mockoljuk az adatbázis hívásokat 
 +    userRepositoryStub = sinon.stub(UserRepository.prototype, 'findUserByEmail'); 
 +    userService = new UserService(new UserRepository()); 
 +  }); 
 + 
 +  afterEach(function() { 
 +    // Restore minden stubolt funkciót a tesztek után 
 +    sinon.restore(); 
 +  }); 
 + 
 +  it('should return an error if the email is already in use', async function() { 
 +    // Szimuláljuk, hogy az email már létezik 
 +    userRepositoryStub.resolves({ email: 'existing@example.com' }); 
 + 
 +    const result = await userService.registerUser('existing@example.com', 'password123'); 
 + 
 +    expect(result.success).to.be.false; 
 +    expect(result.message).to.equal('Email already in use'); 
 +  }); 
 + 
 +  it('should hash the password and register the user if the email is not in use', async function() { 
 +    // Szimuláljuk, hogy az email nem létezik 
 +    userRepositoryStub.resolves(null); 
 + 
 +    // Mockoljuk a bcrypt hash funkciót 
 +    const bcryptStub sinon.stub(bcrypt, 'hash').resolves('hashedPassword'); 
 + 
 +    const result = await userService.registerUser('newuser@example.com', 'plainPassword'); 
 + 
 +    // Ellenőrizzük, hogy a bcrypt hash funkciót hívták 
 +    expect(bcryptStub.calledOnce).to.be.true; 
 +    expect(bcryptStub.calledWith('plainPassword')).to.be.true; 
 +    expect(result.success).to.be.true; 
 +    expect(result.message).to.equal('User registered successfully'); 
 +  }); 
 + 
 +  it('should not call bcrypt hash if the email already exists', async function() { 
 +    // Szimuláljuk, hogy az email már létezik 
 +    userRepositoryStub.resolves({ email: 'existing@example.com' }); 
 + 
 +    const bcryptStub = sinon.stub(bcrypt, 'hash'); 
 + 
 +    const result = await userService.registerUser('existing@example.com', 'plainPassword'); 
 + 
 +    // Ellenőrizzük, hogy a bcrypt hash nem lett meghívva 
 +    expect(bcryptStub.called).to.be.false; 
 +    expect(result.success).to.be.false; 
 +    expect(result.message).to.equal('Email already in use'); 
 +  }); 
 +}); 
 +</sxh> 
 + 
 +A teszt futtatás természetesen hibát ad. 
 + 
 +Hozzuk létre az ''services/userService.js'' implementációt az alábbiak szerint: 
 + 
 +<sxh javascript> 
 +import bcrypt from 'bcrypt';
  
 class UserService { class UserService {
Line 205: Line 289:
     }     }
  
-    // Felhasználó regisztrálása 
     async registerUser(email, password) {     async registerUser(email, password) {
-        // Ellenőrizzük, hogy létezik-e már a felhasználó az e-mail alapján 
         const existingUser = await this.userRepository.findUserByEmail(email);         const existingUser = await this.userRepository.findUserByEmail(email);
         if (existingUser) {         if (existingUser) {
Line 213: Line 295:
         }         }
  
-        // Hash-eljük a jelszót 
         const hashedPassword = await bcrypt.hash(password, 10);         const hashedPassword = await bcrypt.hash(password, 10);
- 
-        // Új felhasználó létrehozása 
         const newUser = { email, password: hashedPassword };         const newUser = { email, password: hashedPassword };
- 
-        // Felhasználó mentése 
         await this.userRepository.saveUser(newUser);         await this.userRepository.saveUser(newUser);
  
Line 226: Line 303:
 } }
  
-module.exports = UserService; +export default UserService;  // CommonJS helyett exportáljuk ESM szintaxissal 
-``` +</sxh>
- +
-### 8. **Tesztek újrafuttatása** +
- +
-Most futtasd újra a teszteket: +
- +
-```bash +
-npm test +
-``` +
- +
-Most a teszteknek sikeresen át kell menniük, mivel az implementáció megfelel a tesztek elvárásainak. +
- +
-### 9. **További tesztek és fejlesztés** +
- +
-A TDD ciklusban a következő lépés az újabb tesztek írása új funkciókra, majd a funkciók implementálása annak érdekében, hogy a tesztek mindig megfeleljenek. A TDD ciklus három lépése a következő: +
-1. **Teszt írása** (a teszt el fog bukni). +
-2. **Implementáció írása** (hogy a teszt átmenjen). +
-3. **Refaktorálás** (a kód minőségének javítása a teszt sikerességének megtartásával). +
- +
-Ezzel a módszerrel mindig biztos lehetsz abban, hogy a kód megfelel a tesztelt követelményeknek. +
tanszek/oktatas/tdd_es_bdd.1728731381.txt.gz · Last modified: 2024/10/12 11:09 by knehez