2

私たちのチームはテストを行ったばかりです。初めてスクラムを使用します。最初のスプリントでは、GUI に 1 つのボタンがあります。ボタンを押すと、テキスト ファイルの内容が (新しいスレッド/タスク内の) データベースに変換されます。GUI は、タスクが開始されたことを示し、タスクの状態をポーリングします。

TDD メソッドを使用してすべてを単体テストする方法を知っています。しかし、完了したら、統合テストを行う必要があります。

統合テストでは、どのような種類のテストを実行する必要がありますか? さまざまなファイルをテストして、データベース内のすべてが正しく入力されていることを確認する必要がありますか? (IE: 関係、varchar(xxx) として保存される特定の形式など?)

もしそうなら: これはかなり複雑ですよね? 1つまたは2つの入力パラメーターはありませんが、テストする変数であるファイル全体(つまり、ファイルの内容!!!)があるためです。この 1 つのボタンを押すだけで、何百、あるいは何千ものテストを行うことができます。悪い点: これらのテスト (つまり、フォーマット) のほとんどは、単体テストで既にテストされています。

インターネット上のほとんどの例は、統合テストとしてテストのような gui を示しています (または、受け入れテストの下の例ですか?): 正しいユーザー名とパスワードでログイン - 入力: 名前 + パスワード - 期待される出力: ホームページへのリダイレクト

間違ったユーザー名および/またはパスワードでログイン - 入力: 名前とパスワード (正しくない) - 期待される出力: 警告 (ログイン失敗、ユーザー名またはパスワードが正しくない)

4

2 に答える 2

2

あなたの質問は、テストと環境構築のためのより良い手順に移行しようとする多くの分野をカバーしています。それでは、まず統合テストに触れてみましょう。

統合テストでは、ほとんどの場合、空のデータベースが必要です。既存の特定のデータセットを指定してテストしているため、そのデータをクエリして目的の結果を得ることができます。

UserFinderクラスのような簡単な例を使用して、システム内で特定の名前のユーザーを検索し、使用可能なモデルを取得できるようにします。

public class UserFinder
{
    private SomeDbContext _dbContext;

    public UserFinder(SomeDbContext dbContext)
    { _dbContext = dbContext }

    public User FindUser(string name)
    { _dbContext.Find<User>(new FindUserByNameQuery(_dbContext, name)); }
}

上記では、かなりごみのクラスですが、データベース内に「Tester」という名前のユーザーを指定して、FindUser( "Tester")を呼び出すと、そのユーザーモデルを取得する必要があることをテストできます。

したがって、このテストの一環として、データベースに予想されるユーザーを設定することから始め、実際のデータベース接続を提供するユーザーファインダーを作成し、「テスター」という名前でデータベースにクエリを実行して、次のことを証明します。そのモデルを取り戻します。

このようにして、IDEビルドスクリプトやコマンドラインなど、あらゆるコンテキストでそのテストを実行できます。テストは自己完結型であり、シナリオを設定し、テストを実行して、受け入れ基準を検証するため、一貫した結果が得られます。次に、そのテストが完了したら、すべてのデータを削除する必要があります。つまり、特定のテストに必要なものだけを設定し、通常はそのテスト内でのみ設定するということです。

理想的には、統合テストと受け入れテストの実行は単体テストよりもかなり遅いため、単体テストでカバーされていないものだけをテストしたいのですが、同時に、自分のようなロジックのみをテストするようにしたいのです。 NHibernateを使用して上記のテストシナリオを簡単に作成できます。証明するのは、NHibernateが機能することだけですが、これは目標ではありません。米国があなたに言うことは不可能ですプロジェクトや達成しようとしていることがわからないため、テストする必要があるものですが、アプリケーションのロジックフロー、およびデータベースまたはファイルシステムに接続するフロー内のポイントを確認する必要があります。または、ビジネスロジックがあるアプリケーションに他の外部境界を渡す場合は、テストシナリオをに配置することをお勧めします。

于 2012-09-14T15:54:38.307 に答える
0

テストしているものを正確に制限する必要があると思います。余暇には、リポジトリとデータ サービスを使用して、EF5 をバックエンドとして使用する MVC4 プロジェクトに取り組んでいます。EntityFramework の動作をモックしようとしましたが、複雑すぎます。そして一般的に、ここでは、DB コンテキストをモックすることはほとんど無意味であることに同意しました。とにかく、マイクロソフトはそれについてテストを行っているので、MS によって既にテストされているものを自分でテストする必要はありません。

私のプロジェクトでは、テスト プロジェクトとそのためのテスト データベースをセットアップしました。ただし、リポジトリは非常に透過的で EF に近いため、テストしません。実際のコンテキストと接続文字列をテスト DB に提供することで、データ サービスをテストしています。テストクラスごとに、データベースを削除して構造を再作成しています。テストごとにデータを再入力しているため、テストは常に同じデータに対して実行されます。

これは統合テストと見なされます。ここでは、データベースにアクセスする前にいくつかのレイヤーを通過しているためです。これらのテストでは、DB のリレーションシップで発生する可能性のあるすべての問題や、DbContext に関するその他の問題を取り上げています。

しかし、統合テストに関して言えば、私のコントローラー (およびその他のオブジェクト) はモックアップされた依存関係 (私は Moq を使用しています) でテストされています。そして、UI についてもう少し詳しくなったら、Web ページ用の Selenium を使っていくつかのテストを作成する予定です。

私のテストプロジェクトの例を次に示します。

[TestFixture]
class ProjectDataServiceTest
{
    private ProjectDataService _projectDataService;
    private DatabaseSeeder _seeder;
    private SiteContext _context;

    [TestFixtureSetUp]
    public void FixtureSetUp()
    {

        _context = new SiteContext(); // connection string is taken from app.config file

        _seeder = new DatabaseSeeder(_context);
        _seeder.InitialiseDb();  // create database structure

        ProjectRepository projectRepository = new ProjectRepository(_context);

        _projectDataService = new ProjectDataService(projectRepository);

    }

    [SetUp]
    public void TestSetUp()
    {
        _seeder.SeedDatabase(); // put some test data from a script
    }

    [TearDown]
    public void TestTearDown()
    {
        _seeder.RemoveData(); // delete everything from all the tables
    }

    /**************** Tests are here! ********************/

    [Test]
    public void CheckDatabaseConnectivity()
    {
        Assert.Pass();
    }

    [Test]
    public void GetNoProjectsForUser()
    {   // should return no project for this user, as nothing is assigned
        var user = _seeder.Users[0];
        var projects = _projectDataService.GetUserProjects(user);

        Assert.IsEmpty(user.UserProjectRoles);
        Assert.IsEmpty(projects);
    }

    [Test]
    public void GetAllProjetsForUser()
    {
        var user = _seeder.Users[2];
        var projects = (List<Project>)_projectDataService.GetUserProjects(user);
        int count = user.UserProjectRoles.Count;

        Assert.AreEqual(count, projects.Count);

        Assert.False(projects.Contains(_seeder.Projects[0]));
    }
 }

コントローラーは、平凡な単体テストの方法でテストされます。

    [TestFixture]
    class ProjectsControllerTest
    {
        private ProjectsController _projectController;

        private Mock<IProjectDataService> _projectDataService;
        private Mock<ICurrentUserService> _currentUserService;

        [SetUp]
        public void SetUp()
        {
            MapperConfig.SetMappings();

            _projectDataService = new Mock<IProjectDataService>();
            _currentUserService = new Mock<ICurrentUserService>();

            _currentUserService.Setup(s => s.GetCurrentAppUser()).Returns(new AppUser());

            _projectController = new ProjectsController(_projectDataService.Object, _currentUserService.Object);
        }


        [Test]
        public void InstanceOfProjectController()
        {
            Assert.IsInstanceOf<ProjectsController>(_projectController);
        }


        [Test]
        public void Index()
        {
            var projects = new List<Project>() { new Project() { Name = "one" }, new Project() { Name = "two" } };

            _projectDataService.Setup(s => s.GetUserProjects(It.IsAny<AppUser>())).Returns(projects);

            var view = _projectController.Index();

            Assert.IsInstanceOf<AutoMapViewResult<List<ProjectViewModel>>>(view);
        }
}

また、自動化されたテストは、実際の人がシステムを通過し、ランダムなボタンをクリックして物事を壊そうとすることに取って代わることはできないことを忘れないでください. 多くの場合、単体テストにはユーザーからのランダムな入力がありません。そして、それを機械で真似するのは非常に困難です。

于 2012-09-14T16:13:26.733 に答える