re:Inventで発表されたAmazon Q Developerの新機能を体験してみた

先日、Amazon Q Developerを使ってドキュメントの生成をやってみました。

miyohide.hatenablog.com

そんな中、先日のre:InventにてAmazon Q Developerにも色々と更新が入りました。詳細は以下のブログ。

aws.amazon.com

今回は以下のブログで紹介されたReactを使ったToDoアプリに対してAmazon Q Developerに対して入った/doc/test/reviewをやってみます。

zenn.dev

/doc

プロジェクトの中身を見てREADMEの作成や更新をやってくれるのが/docということです。実際にやってみると以下の結果が出力されました。

# React Todo Application with TypeScript and Vite

This project is a modern React-based Todo application built with TypeScript and Vite, featuring a robust development environment and testing setup.

The application leverages the power of React for building user interfaces, combined with TypeScript for type safety and improved developer experience. Vite is used as the build tool and development server, providing fast hot module replacement (HMR) and optimized builds.

Key features of this project include:
- React 18 with TypeScript support
- Vite for fast development and optimized production builds
- Jest and React Testing Library for unit and integration testing
- ESLint for code linting and style enforcement
- CSS support with module mapping for testing
- SVG support in tests

## Repository Structure

(省略)

## Usage Instructions

### Installation

Prerequisites:
- Node.js (version 14 or higher)
- npm (version 6 or higher)

(省略)

### Getting Started

(省略)

### Configuration

The project uses several configuration files:

- `tsconfig.json`: Main TypeScript configuration
- `tsconfig.app.json`: TypeScript configuration for the application
- `tsconfig.node.json`: TypeScript configuration for Node.js environment
- `vite.config.ts`: Vite build tool configuration
- `eslint.config.js`: ESLint linter configuration
- `jest.config.js`: Jest testing framework configuration

### Troubleshooting

#### Common Issues

1. Module not found errors
   - Problem: "Cannot find module" or "Module not found" errors during build or runtime
   - Solution: 
     1. Ensure all dependencies are installed: `npm install`
     2. Check import statements for typos
     3. Verify the module exists in `node_modules/`
   - If the issue persists, try deleting `node_modules/` and `package-lock.json`, then run `npm install` again

2. TypeScript compilation errors
   - Problem: TypeScript compiler reports errors during build
   - Solution:
     1. Run `npm run lint` to identify and fix linting issues
     2. Check the specific error messages and fix type issues in the code
     3. Ensure `tsconfig*.json` files are correctly configured

#### Debugging

To enable verbose logging:

(省略)

#### Performance Optimization

- Use the React DevTools profiler to identify performance bottlenecks
- Implement React.memo() for components that re-render frequently with the same props
- Use the `useCallback` and `useMemo` hooks to memoize expensive computations or callback functions

## Data Flow

The application follows a typical React data flow:

1. The entry point `src/main.tsx` renders the main `App` component
2. User interactions trigger state updates in React components
3. State changes cause re-renders of affected components
4. Data flows down through props to child components

(省略)

生成には概ね1分から2分ほどでした。実行前はプロジェクトの中身を見て、「このプロジェクトはこういう機能を持つWebアプリで...」ということを生成してくれるものと思っていたのですが、ちょっと違うようです。上記の例を見る限り、package.jsonの中から読み取れる内容をもとに生成しているような感じがします。実際に何をやっているかは、ソースコードを開いてExplain this selected codeと入力した方が良い感じがします。

ただ、Repository Structureの中に以下のようにそれぞれのファイルの簡易的な説明が生成されていました。これは有用かなと感じます。

- `src/`: Contains the main application source code
  - `main.tsx`: Entry point of the React application
  - `App.tsx`: Main application component
  - `App.spec.tsx`: Test file for the App component
- `eslint.config.js`: ESLint configuration for code linting
- `jest.config.js`: Jest configuration for testing
- `jest.setup.ts`: Setup file for Jest tests
- `package.json`: Project metadata and dependencies
- `tsconfig*.json`: TypeScript configuration files
- `vite.config.ts`: Vite configuration for build and development

また、Data Flowの部分は大規模Reactアプリケーションになるとかなり使えるのでは?と期待できそうでもあります。

/test

単体テストを作ってくれるのですが、現状ではPythonJavaだけをサポートしているようです。

ただ、頑張ってテストを生成してくれました。

実際にどのようなことをテストするかの説明も生成してくれました。

実際に生成されたテストコードは以下の通り。

import { render, screen, fireEvent } from '@testing-library/react';
import { App } from './App';

describe('Todo App', () => {
  // Test initial render
  test('renders todo app with initial empty state', () => {
    render(<App />);

    expect(screen.getByRole('combobox')).toBeInTheDocument();
    expect(screen.getByText('すべてのタスク')).toBeInTheDocument();
    expect(screen.getByRole('textbox')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: '追加' })).toBeInTheDocument();
  });

  // Test adding a todo
  test('can add a new todo', () => {
    render(<App />);

    const input = screen.getByRole('textbox');
    fireEvent.change(input, { target: { value: 'New Todo' } });
    fireEvent.submit(screen.getByRole('button', { name: '追加' }));

    expect(screen.getByDisplayValue('New Todo')).toBeInTheDocument();
    expect(input).toHaveValue(''); // Input should be cleared
  });

  // Test checking a todo
  test('can check/uncheck a todo', () => {
    render(<App />);

    // Add a todo first
    const input = screen.getByRole('textbox');
    fireEvent.change(input, { target: { value: 'Test Todo' } });
    fireEvent.submit(screen.getByRole('button', { name: '追加' }));

    // Find and click the checkbox
    const checkbox = screen.getByRole('checkbox');
    fireEvent.click(checkbox);
    expect(checkbox).toBeChecked();

    // Uncheck
    fireEvent.click(checkbox);
    expect(checkbox).not.toBeChecked();
  });

  // Test filtering todos
  test('can filter todos', () => {
    render(<App />);

    // Add two todos
    const input = screen.getByRole('textbox');
    fireEvent.change(input, { target: { value: 'Todo 1' } });
    fireEvent.submit(screen.getByRole('button', { name: '追加' }));
    fireEvent.change(input, { target: { value: 'Todo 2' } });
    fireEvent.submit(screen.getByRole('button', { name: '追加' }));

    // Check first todo
    const checkboxes = screen.getAllByRole('checkbox');
    fireEvent.click(checkboxes[0]);

    // Filter completed
    const select = screen.getByRole('combobox');
    fireEvent.change(select, { target: { value: 'checked' } });

    expect(screen.getByDisplayValue('Todo 1')).toBeInTheDocument();
    expect(screen.queryByDisplayValue('Todo 2')).not.toBeInTheDocument();
  });

  // Test removing a todo
  test('can remove and restore a todo', () => {
    render(<App />);

    // Add a todo
    const input = screen.getByRole('textbox');
    fireEvent.change(input, { target: { value: 'Remove Test' } });
    fireEvent.submit(screen.getByRole('button', { name: '追加' }));

    // Remove the todo
    fireEvent.click(screen.getByRole('button', { name: '削除' }));

    // Switch to removed items
    const select = screen.getByRole('combobox');
    fireEvent.change(select, { target: { value: 'removed' } });

    // Verify todo is in removed items
    expect(screen.getByDisplayValue('Remove Test')).toBeInTheDocument();

    // Restore the todo
    fireEvent.click(screen.getByRole('button', { name: '復元' }));

    // Switch back to all items
    fireEvent.change(select, { target: { value: 'all' } });
    expect(screen.getByDisplayValue('Remove Test')).toBeInTheDocument();
  });
});

実際にテストを走らせてみましたが、残念ながら5件中4件失敗。

失敗のログを見ると、getByで取得しようとした要素が複数あることから失敗していました。最初っから完璧なものを求めるのではなく、Reactを対象にしたJestのサンプルを出力してくれるというレベルで捉えた方が良いかもしれません。

/review

コードスメルやアンチパターン脆弱性などのチェックをしてくれるそうです。実際にやってみましたが、私の場合は特に問題が検出されませんでした。

もうちょっといろんなパターンでやってみる必要がありそうです。

考察

re:Inventで発表されたAmazon Q Developerの新機能を試してみました。個人的には、/testがかなり有用でした。テストコードの作成はテスティングライブラリの書き方を新たに覚える必要があるので憂鬱なのですが、失敗するとはいえまずは下書きを書いてくれるのは非常に有用と感じました。

そのような考えでいると/docもまずは下書きとして色々と書いてくれるのは有用かなと感じました。一発正解を求めがちですが、まずは今の所下書き生成ツールとして捉えるのが良いのかもしれません。