SG

F# で TFS 上のテスト結果を取得してみた

open System
open Microsoft.TeamFoundation.Client
open Microsoft.TeamFoundation.TestManagement.Client
open Microsoft.TeamFoundation.WorkItemTracking.Client

(* プロジェクトの一覧を取得 *)
let getTestProjectsByProjectCollection (collection : TfsTeamProjectCollection) = 
  let testService = collection.GetService(typeof<ITestManagementService>) :?> ITestManagementService
  let store = collection.GetService(typeof<WorkItemStore>) :?> WorkItemStore
      
  store.Projects
  |> Seq.cast
  |> Seq.map (fun (project : Project) -> testService.GetTeamProject(project))
    
(* Uri からプロジェクトの一覧を取得 *)
let getTestProjectsByUrl uriString = 
  let uri = Uri(uriString)
  let collection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(uri)

  getTestProjectsByProjectCollection collection     
    
(* テスト計画の一覧を取得 *)
let getTestPlans (testProject : ITestManagementTeamProject) = 
  testProject.TestPlans.Query("Select * From TestPlan")
    
(* テストスイート全体のテストスイートの一覧を取得 *)
let getTestSuitesInSuite (suite : ITestSuiteEntry) = 
    
  let rec getSuite (suite : ITestSuiteEntry) = 
        
    match suite.TestSuite with
    | :? IStaticTestSuite
      ->          
        let other = 
          let staticSuite = suite.TestSuite :?> IStaticTestSuite
          staticSuite.Entries
          |> Seq.cast
          |> Seq.collect (fun e -> getSuite e)
          
        if suite.TestCase = null then
          let self = Seq.singleton suite
          Seq.append self other 
        else
          other

    | _ -> 
      Seq.empty

  getSuite suite
    
(* テスト計画全体のテストスイートの一覧を取得 *)
let getTestSuitesInPlan (testPlan : ITestPlan) = 
  testPlan.RootSuite.Entries
  |> Seq.cast
  |> Seq.collect (fun s -> getTestSuitesInSuite s)

(* テストプロジェクト全体のテストスイートの一覧を取得 *)
let getTestSuitesInProject (testProject : ITestManagementTeamProject) = 
  testProject
  |> getTestPlans
  |> Seq.cast 
  |> Seq.collect (fun p -> getTestSuitesInPlan p)

(* 対象のテストスイートで実行された対象のテストの結果を取得 *)
let getTestPointsBySuiteAndTestCase (suite : ITestSuiteEntry) (testcase : ITestCase) = 
  let plan = suite.TestSuite.Plan

  plan.QueryTestPoints(
      sprintf "SELECT * FROM TestPoint Where SuiteId = %A AND TestCaseId = %A" suite.Id testcase.Id)
        
(* 対象のテストスイートで実行されたテストの結果を取得 *)         
let getTestPointsInSuite (suite : ITestSuiteEntry) = 
 
  match suite.TestSuite with
  | :? IStaticTestSuite ->

    let staticSuite = suite.TestSuite :?> IStaticTestSuite
    staticSuite.TestCases
    |> Seq.collect (fun t -> getTestPointsBySuiteAndTestCase suite t.TestCase)

  | _ -> 
    Seq.empty


type TestResult = {
    Id : int;
    Title : string;
    Outcome : TestOutcome
} 
   
[<EntryPoint>]
let main args = 

  let uri = args.[0]
  let projectName = args.[1]
  
  let results = 
    uri
    |> getTestProjectsByUrl
    |> Seq.filter  (fun proj  -> proj.WitProject.Name = projectName)
    |> Seq.collect (fun proj  -> getTestSuitesInProject proj) 
    |> Seq.collect (fun suite -> getTestPointsInSuite suite)
    |> Seq.filter  (fun point -> point.MostRecentResult <> null)
    |> Seq.map     (fun point -> {Id = point.Id;
                                  Title = point.TestCaseWorkItem.Title;
                                  Outcome = point.MostRecentResult.Outcome})
  
  results 
  |> Seq.toList
  |> List.iter (fun result -> printfn "[%d] %s : %A" result.Id result.Title result.Outcome) |> ignore

  0