搜索

PythonReactSEOPDF
GitHub Skill

testdriverreusable-code

Build maintainable test suites with reusable code patterns

testdriverai☆ 217 仓库 Stars33 仓库 Forks

安装与使用

请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。

查看来源 ↗使用指南

技能说明

As your test suite grows, you'll want to extract common patterns into reusable code. This keeps tests DRY, readable, and easy to maintain.

Helper Functions

The simplest approach is extracting common actions into helper functions. Create a helpers/ directory for shared utilities:

export async function login(testdriver, { email, password }) {
  const emailInput = await testdriver.find('email input');
  await emailInput.click();
  await testdriver.type(email);
  
  const passwordInput = await testdriver.find('password input');
  await passwordInput.click();
  await testdriver.type(password);
  
  const loginButton = await testdriver.find('login button');
  await loginButton.click();
  
  const result = await testdriver.assert('user is logged in');
  return result;
}

export async function logout(testdriver) {
  const userMenu = await testdriver.find('user menu');
  await userMenu.click();
  
  const logoutButton = await testdriver.find('logout button');
  await logoutButton.click();
}

❌ Bad: await testdriver.find('profile name TestDriver in the top right')
✅ Good: await testdriver.find('user profile name in the top right')

Hardcoded values like usernames, product names, or prices will cause tests to fail when the data changes. Use generic descriptions that work regardless of the specific content displayed. </Warning>

Now import and use these helpers in any test:

import { describe, expect, it } from "vitest";
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
import { login } from './helpers/auth.js';

describe("Checkout", () => {
  it("should complete checkout as logged in user", async (context) => {
    const testdriver = TestDriver(context);
    
    await testdriver.provision.chrome({
      url: 'https://shop.example.com',
    });

    // Use the helper
    await login(testdriver, { 
      email: 'user@example.com', 
      password: 'password123' 
    });

    // Continue with checkout steps...
    const cartButton = await testdriver.find('cart button');
    await cartButton.click();
  });
});

Page Objects

For larger test suites, the Page Object pattern encapsulates all interactions with a specific page or component:

export class LoginPage {
  constructor(testdriver) {
    this.td = testdriver;
  }

  async enterEmail(email) {
    const input = await this.td.find('email input');
    await input.click();
    await this.td.type(email);
  }

  async enterPassword(password) {
    const input = await this.td.find('password input');
    await input.click();
    await this.td.type(password);
  }

  async submit() {
    const button = await this.td.find('submit button');
    await button.click();
  }

  async login(email, password) {
    await this.enterEmail(email);
    await this.enterPassword(password);
    await this.submit();
  }

  async assertError(message) {
    return await this.td.assert(`error message shows "${message}"`);
  }

  async assertLoggedIn() {
    return await this.td.assert('user dashboard is visible');
  }
}

Use the page object in your tests:

import { describe, expect, it } from "vitest";
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
import { LoginPage } from './pages/LoginPage.js';

describe("Authentication", () => {
  it("should show error for invalid credentials", async (context) => {
    const testdriver = TestDriver(context);
    
    await testdriver.provision.chrome({
      url: 'https://app.example.com/login',
    });

    const loginPage = new LoginPage(testdriver);
    
    await loginPage.login('invalid@test.com', 'wrongpassword');
    
    const hasError = await loginPage.assertError('Invalid credentials');
    expect(hasError).toBeTruthy();
  });

  it("should redirect to dashboard on success", async (context) => {
    const testdriver = TestDriver(context);
    
    await testdriver.provision.chrome({
      url: 'https://app.example.com/login',
    });

    const loginPage = new LoginPage(testdriver);
    
    await loginPage.login('valid@test.com', 'correctpassword');
    
    const isLoggedIn = await loginPage.assertLoggedIn();
    expect(isLoggedIn).toBeTruthy();
  });
});

Shared Test Fixtures

Create reusable fixtures for common test setup scenarios:

export const testUsers = {
  admin: { email: 'admin@example.com', password: 'admin123' },
  regular: { email: 'user@example.com', password: 'user123' },
  guest: { email: 'guest@example.com', password: 'guest123' },
};

export const testUrls = {
  staging: 'https://staging.example.com',
  production: 'https://example.com',
};

export async function setupAuthenticatedSession(testdriver, user = testUsers.regular) {
  const emailInput = await testdriver.find('email input');
  await emailInput.click();
  await testdriver.type(user.email);
  
  const passwordInput = await testdriver.find('password input');
  await passwordInput.click();
  await testdriver.type(user.password);
  
  const loginButton = await testdriver.find('login button');
  await loginButton.click();
  
  await testdriver.assert('user is logged in');
}
import { describe, expect, it } from "vitest";
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
import { testUsers, testUrls, setupAuthenticatedSession } from './fixtures/index.js';

describe("Admin Panel", () => {
  it("should access admin settings", async (context) => {
    const testdriver = TestDriver(context);
    
    await testdriver.provision.chrome({
      url: `${testUrls.staging}/login`,
    });

    await setupAuthenticatedSession(testdriver, testUsers.admin);

    const settingsLink = await testdriver.find('admin settings link');
    await settingsLink.click();
    
    const result = await testdriver.assert('admin settings panel is visible');
    expect(result).toBeTruthy();
  });
});

Suggested Project Structure

Folder Purpose
fixtures/ Test data and setup utilities
helpers/ Reusable helper functions
pages/ Page object classes
specs/ Test files

使用示例

查看来源仓库中的使用示例与配置说明。

查看来源 ↗

来源历史

收录时间
2026-03-11
索引更新时间
2026-03-11
Branch
main

收录与同步日期属于本站记录。源码修改历史请查看来源仓库。

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!