導入
最近、私は NestJS プロジェクトの単体テストと E2E テストを作成しています。バックエンド プロジェクトのテストを作成するのは初めてですが、そのプロセスがフロントエンド テストの経験とは異なるため、始めるのが大変でした。いくつかの例を見た後、テストへの取り組み方をより明確に理解できたので、同じような混乱に直面している他の人を助けるために、記事を書いて自分の学習を記録し共有する予定です。
さらに、関連するユニットと E2E テストが完了したデモ プロジェクトをまとめました。これは興味深いかもしれません。コードは Github にアップロードされました: https://github.com/woai3c/nestjs-demo.
単体テストと E2E テストの違い
単体テストと E2E テストはソフトウェア テストの方法ですが、目的と範囲が異なります。
単体テストには、ソフトウェア内のテスト可能な最小単位のチェックと検証が含まれます。たとえば、関数やメソッドを 1 つの単位とみなすことができます。単体テストでは、関数のさまざまな入力に対して期待される出力を提供し、その動作の正確さを検証します。単体テストの目的は、関数内のバグを迅速に特定することです。また、バグは簡単に記述でき、迅速に実行できます。
一方、E2E テストでは、実際のユーザー シナリオをシミュレートしてアプリケーション全体をテストすることがよくあります。たとえば、フロントエンドは通常、テストにブラウザまたはヘッドレス ブラウザを使用しますが、バックエンドは API 呼び出しをシミュレートすることによってテストを行います。
NestJS プロジェクト内では、Users モジュールの更新メソッドがユーザーを正しく更新するかどうかを検証するなど、単体テストで特定のサービスやコントローラーのメソッドを評価する場合があります。ただし、E2E テストでは、新しいユーザーの作成からパスワードの更新、最終的にはユーザーの削除に至るまで、複数のサービスとコントローラーが関与する完全なユーザー ジャーニーを検査する場合があります。
単体テストの作成
インターフェイスを含まないユーティリティ関数またはメソッドの単体テストを記述するのは比較的簡単です。必要なのは、さまざまな入力を考慮して、対応するテスト コードを作成することだけです。ただし、インターフェイスが登場すると、状況はさらに複雑になります。例としてコードを使用してみましょう:
async validateUser( username: string, password: string, ): Promise<useraccountdto> { const entity = await this.usersService.findOne({ username }); if (!entity) { throw new UnauthorizedException('User not found'); } if (entity.lockUntil && entity.lockUntil > Date.now()) { const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000); let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`; if (diffInSeconds > 60) { const diffInMinutes = Math.round(diffInSeconds / 60); message = `The account is locked. Please try again in ${diffInMinutes} minutes.`; } throw new UnauthorizedException(message); } const passwordMatch = bcrypt.compareSync(password, entity.password); if (!passwordMatch) { // $inc update to increase failedLoginAttempts const update = { $inc: { failedLoginAttempts: 1 }, }; // lock account when the third try is failed if (entity.failedLoginAttempts + 1 >= 3) { // $set update to lock the account for 5 minutes update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 }; } await this.usersService.update(entity._id, update); throw new UnauthorizedException('Invalid password'); } // if validation is sucessful, then reset failedLoginAttempts and lockUntil if ( entity.failedLoginAttempts > 0 || (entity.lockUntil && entity.lockUntil > Date.now()) ) { await this.usersService.update(entity._id, { $set: { failedLoginAttempts: 0, lockUntil: null }, }); } return { userId: entity._id, username } as UserAccountDto; } </useraccountdto>
上記のコードは、auth.service.ts ファイル内のメソッド validateUser であり、主にログイン中にユーザーが入力したユーザー名とパスワードが正しいかどうかを確認するために使用されます。これには次のロジックが含まれています:
- ユーザー名に基づいてユーザーが存在するかどうかを確認します。そうでない場合は、401 例外をスローします (404 例外も可能です)。
- ユーザーがロックアウトされているかどうかを確認します。その場合は、関連するメッセージを含む 401 例外をスローします。
- パスワードを暗号化し、データベース内のパスワードと比較します。正しくない場合は、401 例外をスローします (ログイン試行が 3 回連続して失敗すると、アカウントが 5 分間ロックされます)。
- ログインが成功した場合は、以前に失敗したログイン試行回数 (該当する場合) をクリアし、ユーザー ID とユーザー名を次の段階に返します。
ご覧のとおり、validateUser メソッドには 4 つの処理ロジックが含まれており、validateUser 関数全体が正しく動作していることを確認するには、これら 4 つのポイントに対応する単体テスト コードを記述する必要があります。
最初のテストケース
単体テストの作成を開始すると、問題が発生します。findOne メソッドはデータベースと対話する必要があり、ユーザー名を使用してデータベース内で対応するユーザーを検索します。ただし、すべての単体テストでデータベースと対話する必要がある場合、テストは非常に煩雑になります。したがって、これを達成するために偽のデータを模擬することができます。
たとえば、woai3c という名前のユーザーを登録したとします。次に、ログイン中に、 const enity = await this.usersService.findOne({ username }); を通じて validateUser メソッドでユーザー データを取得できます。このコード行が目的のデータを返すことができれば、データベースとの対話がなくても問題はありません。これはモックデータを通じて実現できます。次に、validateUser メソッドに関連するテスト コードを見てみましょう。
async validateUser( username: string, password: string, ): Promise<useraccountdto> { const entity = await this.usersService.findOne({ username }); if (!entity) { throw new UnauthorizedException('User not found'); } if (entity.lockUntil && entity.lockUntil > Date.now()) { const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000); let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`; if (diffInSeconds > 60) { const diffInMinutes = Math.round(diffInSeconds / 60); message = `The account is locked. Please try again in ${diffInMinutes} minutes.`; } throw new UnauthorizedException(message); } const passwordMatch = bcrypt.compareSync(password, entity.password); if (!passwordMatch) { // $inc update to increase failedLoginAttempts const update = { $inc: { failedLoginAttempts: 1 }, }; // lock account when the third try is failed if (entity.failedLoginAttempts + 1 >= 3) { // $set update to lock the account for 5 minutes update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 }; } await this.usersService.update(entity._id, update); throw new UnauthorizedException('Invalid password'); } // if validation is sucessful, then reset failedLoginAttempts and lockUntil if ( entity.failedLoginAttempts > 0 || (entity.lockUntil && entity.lockUntil > Date.now()) ) { await this.usersService.update(entity._id, { $set: { failedLoginAttempts: 0, lockUntil: null }, }); } return { userId: entity._id, username } as UserAccountDto; } </useraccountdto>
usersService の findOne メソッドを呼び出してユーザー データを取得するため、テスト コードで usersService の findOne メソッドをモックする必要があります。
import { Test } from '@nestjs/testing'; import { AuthService } from '@/modules/auth/auth.service'; import { UsersService } from '@/modules/users/users.service'; import { UnauthorizedException } from '@nestjs/common'; import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants'; describe('AuthService', () => { let authService: AuthService; // Use the actual AuthService type let usersService: Partial<record usersservice jest.mock>>; beforeEach(async () => { usersService = { findOne: jest.fn(), }; const module = await Test.createTestingModule({ providers: [ AuthService, { provide: UsersService, useValue: usersService, }, ], }).compile(); authService = module.get<authservice>(AuthService); }); describe('validateUser', () => { it('should throw an UnauthorizedException if user is not found', async () => { await expect( authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD), ).rejects.toThrow(UnauthorizedException); }); // other tests... }); }); </authservice></record>
jest.fn() を使用して、実際の usersService.findOne() を置き換える関数を返します。ここで usersService.findOne() を呼び出した場合、戻り値はないため、最初の単体テスト ケースはパスします:
beforeEach(async () => { usersService = { findOne: jest.fn(), // mock findOne method }; const module = await Test.createTestingModule({ providers: [ AuthService, // real AuthService, because we are testing its methods { provide: UsersService, // use mock usersService instead of real usersService useValue: usersService, }, ], }).compile(); authService = module.get<authservice>(AuthService); }); </authservice>
const エンティティ内の findOne = await this.usersService.findOne({ username }); validateUser メソッドの は戻り値のない偽の関数であり、validateUser メソッドのコードの 2 行目から 4 行目は実行できます。
it('should throw an UnauthorizedException if user is not found', async () => { await expect( authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD), ).rejects.toThrow(UnauthorizedException); });
401 エラーをスローします。これは予想どおりです。
2 番目のテスト ケース
validateUser メソッドの 2 番目のロジックは、ユーザーがロックされているかどうかを判断するもので、対応するコードは次のとおりです。
if (!entity) { throw new UnauthorizedException('User not found'); }
ご覧のとおり、ユーザー データにロック時間 lockUntil があり、ロック終了時間が現在時刻より大きい場合、現在のアカウントがロックされていると判断できます。したがって、lockUntil フィールドを使用してユーザー データをモックする必要があります:
async validateUser( username: string, password: string, ): Promise<useraccountdto> { const entity = await this.usersService.findOne({ username }); if (!entity) { throw new UnauthorizedException('User not found'); } if (entity.lockUntil && entity.lockUntil > Date.now()) { const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000); let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`; if (diffInSeconds > 60) { const diffInMinutes = Math.round(diffInSeconds / 60); message = `The account is locked. Please try again in ${diffInMinutes} minutes.`; } throw new UnauthorizedException(message); } const passwordMatch = bcrypt.compareSync(password, entity.password); if (!passwordMatch) { // $inc update to increase failedLoginAttempts const update = { $inc: { failedLoginAttempts: 1 }, }; // lock account when the third try is failed if (entity.failedLoginAttempts + 1 >= 3) { // $set update to lock the account for 5 minutes update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 }; } await this.usersService.update(entity._id, update); throw new UnauthorizedException('Invalid password'); } // if validation is sucessful, then reset failedLoginAttempts and lockUntil if ( entity.failedLoginAttempts > 0 || (entity.lockUntil && entity.lockUntil > Date.now()) ) { await this.usersService.update(entity._id, { $set: { failedLoginAttempts: 0, lockUntil: null }, }); } return { userId: entity._id, username } as UserAccountDto; } </useraccountdto>
上記のテスト コードでは、オブジェクト lockedUser が最初に定義されており、これには必要な lockUntil フィールドが含まれています。次に、usersService.findOne.mockResolvedValueOnce(lockedUser); によって実現される findOne の戻り値として使用されます。したがって、 validateUser メソッドが実行されると、その中のユーザー データはモック データとなり、2 番目のテスト ケースを正常に通過させます。
単体テストの範囲
単体テスト カバレッジ (コード カバレッジ) は、アプリケーション コードのどれだけが単体テストによってカバーまたはテストされたかを説明するために使用される指標です。通常、これはパーセンテージで表され、考えられるすべてのコード パスのうちどれだけがテスト ケースによってカバーされているかを示します。
単体テストのカバレッジには通常、次のタイプが含まれます:
- 行カバレッジ: テストでカバーされるコードの行数。
- 関数カバレッジ: テストの対象となる関数またはメソッドの数。
- ブランチ カバレッジ: テストでカバーされるコード ブランチの数 (例: if/else ステートメント)。
- ステートメント カバレッジ: コード内のテストの対象となるステートメントの数。
単体テストのカバレッジは単体テストの品質を測定するための重要な指標ですが、それだけが唯一の指標ではありません。カバレッジ率が高いとコード内のエラーを検出しやすくなりますが、コードの品質が保証されるわけではありません。カバレッジ率が低いということは、テストされていないコードが存在し、検出されていないエラーがある可能性があることを意味する可能性があります。
下の画像は、デモ プロジェクトの単体テスト カバレッジの結果を示しています。
サービスやコントローラーなどのファイルの場合は、単体テストのカバレッジが高い方が一般的に良いのですが、モジュールのようなファイルの場合は、単体テストを書く必要はなく、意味がないので書くこともできません。上の画像は、単体テスト カバレッジ全体の全体的なメトリクスを表しています。特定の関数のテスト カバレッジを表示したい場合は、プロジェクトのルート ディレクトリにあるcoverage/lcov-report/index.html ファイルを開くことができます。たとえば、validateUser メソッドの特定のテスト状況を確認したいとします。
ご覧のとおり、validateUser メソッドの元の単体テスト カバレッジは 100% ではなく、実行されなかったコード行がまだ 2 行あります。ただし、4 つの主要な処理ノードには影響しないため、これはあまり重要ではありません。また、一次元的に高いテスト カバレッジを追求すべきではありません。
E2E テストの作成
単体テストでは、模擬データを使用して、各機能が確実にテストできることを確認して、 validateUser() 関数の各機能の単体テストを作成する方法を示しました。 e2E テストでは、実際のユーザー シナリオをシミュレートする必要があるため、テストのためにデータベースに接続する必要があります。したがって、テストする auth.service.ts モジュール内のメソッドはすべてデータベースと対話します。
認証モジュールには主に次の機能が含まれています:
- 登録
- ログイン
- トークンのリフレッシュ
- ユーザー情報の読み取り
- パスワードの変更
- ユーザーの削除
E2E テストでは、ユーザーの登録から削除まで、これら 6 つの機能を 1 つずつテストする必要があります。テスト中に、テストを実行する専用のテスト ユーザーを作成し、テスト データベースに不要な情報が残らないように、完了時にこのテスト ユーザーを削除できます。
async validateUser( username: string, password: string, ): Promise<useraccountdto> { const entity = await this.usersService.findOne({ username }); if (!entity) { throw new UnauthorizedException('User not found'); } if (entity.lockUntil && entity.lockUntil > Date.now()) { const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000); let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`; if (diffInSeconds > 60) { const diffInMinutes = Math.round(diffInSeconds / 60); message = `The account is locked. Please try again in ${diffInMinutes} minutes.`; } throw new UnauthorizedException(message); } const passwordMatch = bcrypt.compareSync(password, entity.password); if (!passwordMatch) { // $inc update to increase failedLoginAttempts const update = { $inc: { failedLoginAttempts: 1 }, }; // lock account when the third try is failed if (entity.failedLoginAttempts + 1 >= 3) { // $set update to lock the account for 5 minutes update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 }; } await this.usersService.update(entity._id, update); throw new UnauthorizedException('Invalid password'); } // if validation is sucessful, then reset failedLoginAttempts and lockUntil if ( entity.failedLoginAttempts > 0 || (entity.lockUntil && entity.lockUntil > Date.now()) ) { await this.usersService.update(entity._id, { $set: { failedLoginAttempts: 0, lockUntil: null }, }); } return { userId: entity._id, username } as UserAccountDto; } </useraccountdto>
beforeAll フック関数はすべてのテストが開始される前に実行されるため、ここでテスト アカウント TEST_USER_NAME を登録できます。 afterAll フック関数はすべてのテストが終了した後に実行されるため、ここでテスト アカウント TEST_USER_NAME を削除するのに適しており、また、登録および削除関数のテストにも便利です。
前のセクションの単体テストでは、validateUser メソッドに関連する単体テストを作成しました。実際には、このメソッドはログイン時に実行され、ユーザーのアカウントとパスワードが正しいかどうかを検証します。したがって、この e2E テストでもログイン プロセスを使用して、e2E テスト ケースの作成方法を示します。
ログイン テスト プロセス全体には、次の 5 つの小さなテストが含まれます。
import { Test } from '@nestjs/testing'; import { AuthService } from '@/modules/auth/auth.service'; import { UsersService } from '@/modules/users/users.service'; import { UnauthorizedException } from '@nestjs/common'; import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants'; describe('AuthService', () => { let authService: AuthService; // Use the actual AuthService type let usersService: Partial<record usersservice jest.mock>>; beforeEach(async () => { usersService = { findOne: jest.fn(), }; const module = await Test.createTestingModule({ providers: [ AuthService, { provide: UsersService, useValue: usersService, }, ], }).compile(); authService = module.get<authservice>(AuthService); }); describe('validateUser', () => { it('should throw an UnauthorizedException if user is not found', async () => { await expect( authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD), ).rejects.toThrow(UnauthorizedException); }); // other tests... }); }); </authservice></record>
これら 5 つのテストは次のとおりです:
- ログインに成功すると、200 を返します
- ユーザーが存在しない場合は、401 例外をスローします
- パスワードまたはユーザー名が指定されていない場合は、400 例外をスローします
- 間違ったパスワードでログインすると、401 例外がスローされます
- アカウントがロックされている場合は、401 例外をスローします
それでは、e2E テストの作成を開始しましょう:
beforeEach(async () => { usersService = { findOne: jest.fn(), // mock findOne method }; const module = await Test.createTestingModule({ providers: [ AuthService, // real AuthService, because we are testing its methods { provide: UsersService, // use mock usersService instead of real usersService useValue: usersService, }, ], }).compile(); authService = module.get<authservice>(AuthService); }); </authservice>
e2E テスト コードの作成は比較的簡単です。インターフェイスを呼び出して結果を確認するだけです。たとえば、ログイン テストが成功した場合、返される結果が 200 であることを確認するだけです。
最初の 4 つのテストは非常に簡単です。次に、アカウントがロックされているかどうかを確認する、少し複雑な e2E テストを見てみましょう。
async validateUser( username: string, password: string, ): Promise<useraccountdto> { const entity = await this.usersService.findOne({ username }); if (!entity) { throw new UnauthorizedException('User not found'); } if (entity.lockUntil && entity.lockUntil > Date.now()) { const diffInSeconds = Math.round((entity.lockUntil - Date.now()) / 1000); let message = `The account is locked. Please try again in ${diffInSeconds} seconds.`; if (diffInSeconds > 60) { const diffInMinutes = Math.round(diffInSeconds / 60); message = `The account is locked. Please try again in ${diffInMinutes} minutes.`; } throw new UnauthorizedException(message); } const passwordMatch = bcrypt.compareSync(password, entity.password); if (!passwordMatch) { // $inc update to increase failedLoginAttempts const update = { $inc: { failedLoginAttempts: 1 }, }; // lock account when the third try is failed if (entity.failedLoginAttempts + 1 >= 3) { // $set update to lock the account for 5 minutes update['$set'] = { lockUntil: Date.now() + 5 * 60 * 1000 }; } await this.usersService.update(entity._id, update); throw new UnauthorizedException('Invalid password'); } // if validation is sucessful, then reset failedLoginAttempts and lockUntil if ( entity.failedLoginAttempts > 0 || (entity.lockUntil && entity.lockUntil > Date.now()) ) { await this.usersService.update(entity._id, { $set: { failedLoginAttempts: 0, lockUntil: null }, }); } return { userId: entity._id, username } as UserAccountDto; } </useraccountdto>
ユーザーが 3 回連続でログインに失敗すると、アカウントはロックされます。したがって、このテストでは、テスト アカウント TEST_USER_NAME を使用できません。テストが成功すると、このアカウントはロックされ、次のテストを続行できなくなります。特にアカウント ロックをテストするために別の新しいユーザー TEST_USER_NAME2 を登録し、テストが成功したらこのユーザーを削除する必要があります。ご覧のとおり、この e2E テストのコードは非常に充実しており、セットアップと分解に多くの作業が必要ですが、実際のテスト コードは次の数行だけです。
import { Test } from '@nestjs/testing'; import { AuthService } from '@/modules/auth/auth.service'; import { UsersService } from '@/modules/users/users.service'; import { UnauthorizedException } from '@nestjs/common'; import { TEST_USER_NAME, TEST_USER_PASSWORD } from '@tests/constants'; describe('AuthService', () => { let authService: AuthService; // Use the actual AuthService type let usersService: Partial<record usersservice jest.mock>>; beforeEach(async () => { usersService = { findOne: jest.fn(), }; const module = await Test.createTestingModule({ providers: [ AuthService, { provide: UsersService, useValue: usersService, }, ], }).compile(); authService = module.get<authservice>(AuthService); }); describe('validateUser', () => { it('should throw an UnauthorizedException if user is not found', async () => { await expect( authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD), ).rejects.toThrow(UnauthorizedException); }); // other tests... }); }); </authservice></record>
e2E テスト コードの作成は比較的簡単です。模擬データやテスト カバレッジを考慮する必要はありません。システムプロセス全体が期待どおりに実行されれば十分です。
テストを書くかどうか
可能であれば、通常はテストを書くことをお勧めします。これにより、システムの堅牢性、保守性、開発効率が向上します。
システムの堅牢性の強化
コードを記述するときは、通常、コア機能が適切に動作することを確認するために、通常の入力でのプログラム フローに重点を置きます。ただし、異常な入力などの特殊なケースは見落とされることがよくあります。テストを書くとこれが変わります。このような場合にどのように対処するかを検討し、適切に対応することでクラッシュを防ぐ必要があります。テストを書くことは間接的にシステムの堅牢性を向上させると言えます。
保守性の向上
包括的なテストを含む新しいプロジェクトを引き継ぐのは、とても楽しいことです。これらはガイドとして機能し、さまざまな機能をすぐに理解するのに役立ちます。関数のコードを 1 行ずつ確認することなく、テスト コードを見るだけで、各関数の期待される動作と境界条件を簡単に把握できます。
開発効率の向上
しばらく更新されていなかったプロジェクトが突然新しい要件を受け取ったと想像してください。変更を加えた後、バグが発生するのではないかと心配になるかもしれません。テストがなければ、プロジェクト全体を手動で再度テストする必要があり、時間が無駄になり非効率的になります。完全なテストでは、コードの変更が既存の機能に影響を与えているかどうかを 1 つのコマンドで知ることができます。エラーがあった場合でも、すぐに特定して対処できます。
テストを書いてはいけない場合は?
短期プロジェクトや要件の反復が非常に速いプロジェクトの場合、テストを作成することはお勧めできません。たとえば、イベントが終了すると役に立たなくなるイベント用のプロジェクトにはテストが必要ありません。また、要件の反復が非常に速いプロジェクトの場合、テストを作成すると開発効率が向上すると言いましたが、それは関数の反復が遅いという前提に基づいています。完了した関数が 1 ~ 2 日で変更される場合は、関連するテスト コードを書き直す必要があります。したがって、テストを作成するのは非常に時間がかかり、労力を費やす価値がないため、テストをまったく作成せず、代わりにテスト チームに頼る方が良いでしょう。
結論
NestJS プロジェクトの単体テストと e2E テストの作成方法を詳しく説明した後、テストの重要性を繰り返しておきたいと思います。システムの堅牢性、保守性、開発効率を向上させることができます。テストを作成する機会がない場合は、自分で練習プロジェクトを開始するか、オープンソース プロジェクトに参加してコードを貢献することをお勧めします。オープンソース プロジェクトには通常、より厳しいコード要件があります。コードに貢献するには、新しいテスト ケースを作成したり、既存のテスト ケースを変更したりすることが必要になる場合があります。
参考資料
- NestJS: 効率的でスケーラブルな Node.js サーバー側アプリケーションを構築するためのフレームワーク。
- MongoDB: データ ストレージに使用される NoSQL データベース。
- Jest: JavaScript と TypeScript のテスト フレームワーク。
- スーパーテスト: HTTP サーバーをテストするためのライブラリ。
以上がNestJS アプリケーションの単体テストと Etest を作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScript文字列置換法とFAQの詳細な説明 この記事では、javaScriptの文字列文字を置き換える2つの方法について説明します:内部JavaScriptコードとWebページの内部HTML。 JavaScriptコード内の文字列を交換します 最も直接的な方法は、置換()メソッドを使用することです。 str = str.replace( "find"、 "置換"); この方法は、最初の一致のみを置き換えます。すべての一致を置き換えるには、正規表現を使用して、グローバルフラグGを追加します。 str = str.replace(/fi

それで、あなたはここで、Ajaxと呼ばれるこのことについてすべてを学ぶ準備ができています。しかし、それは正確には何ですか? Ajaxという用語は、動的でインタラクティブなWebコンテンツを作成するために使用されるテクノロジーのゆるいグループ化を指します。 Ajaxという用語は、もともとJesse Jによって造られました

10の楽しいjQueryゲームプラグインして、あなたのウェブサイトをより魅力的にし、ユーザーの粘着性を高めます! Flashは依然としてカジュアルなWebゲームを開発するのに最適なソフトウェアですが、jQueryは驚くべき効果を生み出すこともできます。また、純粋なアクションフラッシュゲームに匹敵するものではありませんが、場合によってはブラウザで予期せぬ楽しみもできます。 jquery tic toeゲーム ゲームプログラミングの「Hello World」には、JQueryバージョンがあります。 ソースコード jQueryクレイジーワードコンポジションゲーム これは空白のゲームであり、単語の文脈を知らないために奇妙な結果を生み出すことができます。 ソースコード jquery鉱山の掃引ゲーム

このチュートリアルでは、jQueryを使用して魅惑的な視差の背景効果を作成する方法を示しています。 見事な視覚的な深さを作成するレイヤー画像を備えたヘッダーバナーを構築します。 更新されたプラグインは、jQuery 1.6.4以降で動作します。 ダウンロードしてください

記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

この記事では、ブラウザでJavaScriptのパフォーマンスを最適化するための戦略について説明し、実行時間の短縮、ページの負荷速度への影響を最小限に抑えることに焦点を当てています。

Matter.jsは、JavaScriptで書かれた2D Rigid Body Physics Engineです。このライブラリは、ブラウザで2D物理学を簡単にシミュレートするのに役立ちます。剛体を作成し、質量、面積、密度などの物理的特性を割り当てる機能など、多くの機能を提供します。また、重力摩擦など、さまざまな種類の衝突や力をシミュレートすることもできます。 Matter.jsは、すべての主流ブラウザをサポートしています。さらに、タッチを検出し、応答性が高いため、モバイルデバイスに適しています。これらの機能はすべて、物理ベースの2Dゲームまたはシミュレーションを簡単に作成できるため、エンジンの使用方法を学ぶために時間をかける価値があります。このチュートリアルでは、このライブラリのインストールや使用法を含むこのライブラリの基本を取り上げ、

この記事では、JQueryとAjaxを使用して5秒ごとにDivのコンテンツを自動的に更新する方法を示しています。 この例は、RSSフィードからの最新のブログ投稿と、最後の更新タイムスタンプを取得して表示します。 読み込み画像はオプションです


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ドリームウィーバー CS6
ビジュアル Web 開発ツール

WebStorm Mac版
便利なJavaScript開発ツール

ホットトピック



