Couple of days ago I wrote about How To Change Test Scribe Template since than I got plenty of emails on that subject asking me to supply more and more information about changing Test Scribe Template.
Many people thinks that:
“The output generated by Test Scribe is not customizable in this release.”
But this is not fully correct, you can change the Test Scribe template but this will require couple of hacks….. But possible 
I recommend you to read the How To Change Test Scribe Template article to understand what need to be change and more about the tt files, controls the Test Scribe document.
Test Scribe Command List
Text
Add text to the Test Scribe document you need to use the SprText command:
SprText(“Hello World”)
To use built in string reference (table bellow) you need to call SprHost.Resources.GetString(Name)
SprText(SprHost.Resources.GetString("TestCaseLabel"))
SprText(“Section Name”, SprHost.Resources.GetString("TestCaseLabel"))
Using String.Format:
TestCasesLabel = Test Cases ({0})
SprText(String.Format(CultureInfo.CurrentCulture, SprHost.Resources.GetString("TestCasesLabel"), suite.AllTestCases.Count))
Hyperlink
Hyperlinks in Test Scribe are very powerful, you can add links that will activate MTM objects directly or just a simple hyperlink.
SprHyperlink(Text, Uri Value)
How to open Test Plan (In MTM) From the Word Document using the BuildUrl method:
SprHyperlink(TestPlan.Id.ToString(), BuildUrl("testing/testplan/open?id=" + TestPlan.Id.ToString()))
Result: mtm://localhost:8080/tfs/defaultcollection/p:TeamProject/testing/testplan/open?id=3

Images
Adding built in images or new images as follow:
SprImage("/Images/TestCase_16.png")

Paragraph
This is with no doubt the must popular method you will use when customizing the Test Scribe Template, Create new Paragraph.
Inside the paragraph you can use all the above methods.
SprParagraph
(
"Heading4",
SprImage("/Images/TestCase_16.png"),
SprText(SprHost.Resources.GetString("TestCaseLabel")),
SprHyperlink(testCase.Id.ToString(), BuildUrl("testing/testcase/open?id=" +
testCase.Id.ToString())),
SprText(String.Format(CultureInfo.CurrentCulture, SprHost.Resources.GetString
"ItemHeaderFmtString"), testCase.Title))
);
Test Scribe Images Reference
There are set of images inside “Microsoft.TeamFoundation.TestManagement.Tools.TestScribe.dll”, you can add your own images inside the template.
| Name | Value |
| Aborted_16 | ![clip_image001[6] clip_image001[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0016_thumb_21ADCD16.png) |
| Blocked_16 | ![clip_image002[6] clip_image002[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0026_thumb_4DEA53FA.png) |
| Bug_16 | ![clip_image003[6] clip_image003[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0036_thumb_451A4BAE.png) |
| Error_16 | ![clip_image004[6] clip_image004[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0046_thumb_7156D292.png) |
| Failed_16 | ![clip_image005[6] clip_image005[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0056_thumb_368F29BC.png) |
| Inconclusive_16 | ![clip_image006[6] clip_image006[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0066_thumb_2DBF2170.png) |
| InProgress_16 | ![clip_image007[6] clip_image007[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0076_thumb_56E6B9AE.png) |
| None_16 | ![clip_image008[6] clip_image008[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0086_thumb_13BB3B81.png) |
| NotExecuted_16 | ![clip_image009[6] clip_image009[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0096_thumb_10C5D6CE.png) |
| Passed_16 | ![clip_image010[6] clip_image010[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0106_thumb_3576EE45.png) |
| Paused_16 | ![clip_image011[6] clip_image011[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0116_thumb_217D5BAF.png) |
| Pending_16 | ![clip_image012[6] clip_image012[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0126_thumb_1F605CE6.png) |
| Queued_16 | ![clip_image013[6] clip_image013[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0136_thumb_565A3B1F.png) |
| RunComplete_16 | ![clip_image014[6] clip_image014[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0146_thumb_348E628E.png) |
| RunInitializing_16 | ![clip_image015[6] clip_image015[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0156_thumb_0BA34D85.png) |
| SharedStepSet_16 | ![clip_image016[6] clip_image016[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0166_thumb_252ADAB2.png) |
| TestCase_16 | ![clip_image017[6] clip_image017[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0176_thumb_02F2CF2C.png) |
| TestConfiguration_16 | ![clip_image018[6] clip_image018[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0186_thumb_599B872D.png) |
| TestConfiguration_32 | ![clip_image019[6] clip_image019[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0196_thumb_700E25B4.png) |
| TestPlan_16 | ![clip_image020[6] clip_image020[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0206_thumb_2D4EDA7C.png) |
| TestPlan_32 | ![clip_image021[6] clip_image021[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0216_thumb_3D0E6F80.png) |
| TestSettings_16 | ![clip_image022[6] clip_image022[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0226_thumb_61BF86F7.png) |
| TestSettings_32 | ![clip_image023[6] clip_image023[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0236_thumb_43B15336.png) |
| TestStep_16 | ![clip_image024[6] clip_image024[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0246_thumb_00F207FE.png) |
| TestStepValidate_16 | ![clip_image025[6] clip_image025[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0256_thumb_702A5D4F.png) |
| TestSuiteDynamic_16 | ![clip_image026[6] clip_image026[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0266_thumb_497BD102.png) |
| TestSuiteRequirement_16 | ![clip_image027[6] clip_image027[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0276_thumb_475ED239.png) |
| TestSuiteStatic_16 | ![clip_image028[6] clip_image028[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0286_thumb_3E2296F8.png) |
| Timeout_16 | ![clip_image029[6] clip_image029[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0296_thumb_4324D4A7.png) |
| Warning_16 | ![clip_image030[6] clip_image030[6]](http://blogs.microsoft.co.il/blogs/shair/clip_image0306_thumb_33358FE3.png) |
Test Scribe String Reference
When customizing the Test Scribe template you can use the default values inside “Microsoft.TeamFoundation.TestManagement.Tools.TestScribe.dll” to avoid static text inside the tt file extension.
| Name | Value |
| ActiveDatesLabel | Active dates: |
| AdditionalNotesHeaderLabel | Additional Notes |
| AreaLabel | Area: |
| AssignedToLabel | Assigned to: |
| AutomatedTestNameLabel | Automated test: |
| AutomatedTestRunLabel | Automated |
| AutomatedTestSettingsLabel | Automated Settings {0}: {1} |
| AutomatedTestType | Automated |
| BugLabel | Bug |
| BugsLoggedLabel | Bug(s) logged: |
| BuildDefinitionLabel | Build definition: |
| BuildLabel | Build: |
| BuildNumberLabel | Build(s): |
| BuildQualityLabel | Build quality: |
| BuildUnassignedLabel | Unassigned |
| CommaSeparator | {0} |
| CompletedWithIssues | completed with issues. |
| ConfigDetailsDescription | You can use one or more configuration variables to create a test configuration. Each configuration variable defines one characteristic of the testing environment. For example |
| ConfigurationDetailsHeaderLabel | Configuration Details |
| ConfigurationLabel | Config {0}: {1} |
| ControllerNoLongerExists | <Agent no longer exists> |
| DateRangeSeparator | - |
| DayFormatString | {0} day{1}{2} |
| DurationLabel | Duration: |
| EnterNotesHereLabel | <Enter notes here> |
| EnvironmentNoLongerExists | <Environment no longer exists> |
| ExpectedValueColumnHeader | Expected Value |
| Failed | failed. |
| FailedTestsByTypeChartLabel | Failed Tests by Type |
| FailureType_KnownIssue | Known issue |
| FailureType_KnownIssues | Known issues |
| FailureType_NewIssue | New issue |
| FailureType_NewIssues | New issues |
| FailureType_Regression | Regression |
| FailureType_Regressions | Regressions |
| FailureType_Unknown | Unknown |
| FailureTypeLabel | Failure type: |
| HourFormatString | {0} hour{1}{2} |
| IncludedRunsHeaderLabel | Included Runs ({0}) |
| InProgress | in progress. |
| ItemHeaderFmtString | : {0} |
| IterationLabel | Iteration: |
| LocalOnlyEnvironmentName | <Local> |
| ManualTestRunLabel | Manual |
| ManualTestSettingsLabel | Manual Settings {0}: {1} |
| ManualTestType | Manual |
| MetadataLabelFormat | {0}: |
| MinuteFormatString | {0} minute{1} |
| NameValueSeparator | | |
| NoBugsLinkedLabel | No bugs logged |
| NoBuildAssigned | <Not assigned> |
| NoControllerUsed | <No agent used> |
| NoResultsFoundLabel | No results found. |
| NotSetLabel | Not set |
| OtherTestResolutionName | {0} Others ({1}%) |
| Outcome_Unspecified | Active |
| OutcomeSummaryHeaderLabel | Outcome Summary |
| OwnerLabel | Owner: |
| Passed | passed successfully. |
| PlanState_Active | Active |
| PlanState_Inactive | Inactive |
| PriorityLabel | Priority: |
| RelatedBugsHeader | Related Bugs ({0}) |
| ResultLabel | (result) |
| RunByLabel | Run by: |
| RunDateStartedLabel | Date started: |
| RunTypeLabel | Run type: |
| SecondFormatString | {0} second{1} |
| SingleTestRunSummaryHeader | Test run {0}: {1} {2} |
| State_Aborted | Aborted |
| State_Blocked | Blocked |
| State_Error | Error |
| State_Failed | Failed |
| State_Inconclusive | Inconclusive |
| State_None | None |
| State_NotExecuted | Not executed |
| State_NotStarted | Not started |
| State_Passed | Passed |
| State_Timeout | Timeout |
| State_Waiting | Waiting for Test Controller |
| State_Warning | Warning |
| StatisticFormatString | {0} {1} ({2}%) |
| StepNumberColumnHeader | # |
| SuiteDetailsDescription | You can group your test cases together by organizing test cases into a test suite hierarchy in your test plan. By grouping your test cases together |
| SuiteDetailsLabel | Suite Details |
| SuiteEntryLabel | Suite {0}: {1} |
| SuiteHierarchyLabel | Suite Hierarchy |
| SuiteState_Completed | Completed |
| SuiteState_InPlanning | In planning |
| SuiteState_InProgress | In progress |
| SuiteState_None | None |
| TestAnalysisByTypeChartLabel | Test Analysis by Type |
| TestCaseLabel | Test Case |
| TestCasesLabel | Test Cases ({0}) |
| TestControllerLabel | Test controller: |
| TestEnvironmentLabel | Test environment: |
| TestOutcomeChartLabel | Test Outcome |
| TestPlanAvailableConfigsLabel | Available Configurations ({0}) |
| TestPlanLabel | Test plan |
| TestPlanSectionDescription | A test plan lets you specify what you want to test and how to run those tests. A test plan can be applied to a specific iteration of your project. You can have just one default test suite for your test cases |
| TestPlanSectionDescription2 | You can also select the default configurations to use to run the tests in your test plan. The test configuration informs the tester of the set up that is required for these tests. You can have one or multiple default configurations. A test result is recorded every time that you run the test with a specific configuration. A test plan enables you to measure your testing progress |
| TestPlanSectionText | Test Plan Details |
| TestPlanStatusLabel | Status: |
| TestPlanTestSettingsLabel | Test Settings |
| TestResolutionLabel | Test resolution: |
| TestRunDetails_BuildSummaryDisplay | {0} (Platform: {1} |
| TestRunLabel | Test Run |
| TestRunState_Aborted | aborted |
| TestRunState_Completed | completed |
| TestRunState_InProgress | in progress |
| TestRunState_NotStarted | not started |
| TestRunState_Waiting | waiting |
| TestRunSummaryHeader | {0} Test run{1} {2} |
| TestRunSummaryHeader_WithIssuesLabel | with issues |
| TestSettingsDetailsDescription | Test settings use diagnostic data adapters |
| TestSettingsDetailsHeaderLabel | Settings Details |
| TestSettingsLabel | Test settings: |
| TestStepsLabel | Test Steps ({0}) |
| TestSuiteState | State: |
| TimespanInProgress | in progress |
| TimespanLabel | Timespan: |
| TitleColumnHeader | Title |
| TitleHeaderColumnHeader | Title |
| TypeLabel | Type: |
| TypeNone | {0} None ({1}%) |
| UnanalyzedFailuresByOwnerChartLabel | Unanalyzed Failures by Owner |
| UnassignedFailureHeaderLabel | Unanalyzed Failures ({0}) |
I’ve wrote about Test Scribe couple of months ago and explained how you can Generate word documents from Microsoft Test Manager.
Test Scribe is an awesome tool for Generating Test Documents, but can I change the document template? Test Scribe comes with a Default Template and many customers what’s to change the template to their needs.
This is the best way I found how to do that, and it require to drill down to some file inside the Test Scribe.
Make Sure you backup all files before doing any changes!!
Locate Test Scribe Template
Navigate to –>
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\TeamTest
Copy “Microsoft.TeamFoundation.TestManagement.Tools.TestScribe.sx” to another folder, change the file name and extension to “Microsoft.TeamFoundation.TestManagement.Tools.TestScribe.zip”.
Extract file content, and you should have TestPlan and TestRunSummary folder contains the Document Template.

Test Plan Directory Content:

Changing Test Plan Section
I’ve open “TestPlan” directory and start editing the “TestPlanSection.tt”.
In the picture below you can see the two selected Paragraphs that are responsible to the static text display in the header of the document.

I’ve remove those and also changed the Header style, instead of showing the Test Plan Id I wanted to only show the Test Plan Name and make sure the Name is hyper link to the Test Plan it self.
SprParagraph
(
"Heading1",
SprImage("/Images/TestPlan_32.png"),
SprText(SprHost.Resources.GetString("TestPlanLabel")),
SprText(String.Format(CultureInfo.CurrentCulture,
SprHost.Resources.GetString("ItemHeaderFmtString"),
"")),
SprHyperlink(TestPlan.Name, BuildUrl("testing/testplan/open?id="
+ TestPlan.Id.ToString()))
);

Adding Attachments
This is another issue I keep hearing from many customers, How can I add attachments to the document?
In the TestCaseSection.tt just before the “SprMultilineText("Errormessage", testCase.Description);”
Add the following:
if (testCase.Attachments.Count > 0)
{
SprParagraph
(
"Heading4",
SprText("Attachments"),
SprText(String.Format(CultureInfo.CurrentCulture,
SprHost.Resources.GetString("ItemHeaderFmtString"),
testCase.Attachments.Count))
);
for (int i = 0; i < testCase.Attachments.Count; i++)
{
ITestAttachment attachement = testCase.Attachments[i];
SprParagraph
(
"Heading5",
SprText(String.Format(CultureInfo.CurrentCulture, "{0}: ", i + 1)),
SprHyperlink(attachement.Name, attachement.Uri.AbsoluteUri)
);
}
}

Download Custom Template (Backup and Copy to C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\TeamTest)
This is for now, I’ll continue customizing the template over the next weeks.
Enjoy
Last week me and other 20 guys from Sela Group were in the Build Conference where we first saw the new Windows 8 operation system and many cool things coming from Microsoft in the new release.
I have much to say about new things regarding ALM, Metro but as always I prefer to start with building something with the new technology instead of talking about it….
So now I’ll talk about my first Metro Application for Windows 8 called – Metro Puzzle based on Puzzle 15 also called the N-Puzzle.

Step 1: Prepare your environment
To Get started with Metro Applications you need Windows 8 Developer Preview installed with Developer Tools – Download Here
Windows Developer Preview works great on the same hardware that powers Windows Vista and Windows 7:
- 1 gigahertz (GHz) or faster 32-bit (x86) or 64-bit (x64) processor
- 1 gigabyte (GB) RAM (32-bit) or 2 GB RAM (64-bit)
- 16 GB available hard disk space (32-bit) or 20 GB (64-bit)
- DirectX 9 graphics device with WDDM 1.0 or higher driver
- Taking advantage of touch input requires a screen that supports multi-touch
- To run Metro style Apps, you need a screen resolution of 1024 X 768 or greater
Step 2: Create Project
With the new Developer Tools you’ll be able to create Windows Metro Style applications in C#, Visual Basic, C++ and JavaScript.

There are very cool templates for getting started with Metro application, Grid and Split but from my puzzle I’ve created new Application Project.
Step 3: Add Metro Application Bar
Because Windows 8 should support Touch systems Microsoft create the ApplicationBar object to allow users without Mouse to perform Right Click operation just by sliding the finger from the bottom of the screen up.
Of course if you do working with Mouse you can just right click and the application bar will appear.

So How?
Just add the ApplicationBar control just before the end of the XAML file and make sure the ApplicationBar height is 88 (Metro Standard).
<ApplicationBar Grid.ColumnSpan="9" Height="88" Grid.Row="9"
VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal">
<Button Content="Exit" Style="{StaticResource BackButtonStyle}"
x:Name="btnBack" Click="btnBack_Click" />
<Button Content="New Game"
Style="{StaticResource RefreshButtonStyle}"
x:Name="btnnewGame" Click="btnnewGame_Click"/>
</StackPanel>
</ApplicationBar>
Step 4: Add Toast
Toast is the way to notify your user about something, instead of using the annoying Message Box you now Toast the user.
The toast will appear on the right bottom and will not prevent from the user to continue working, the toast will disappear after couple of seconds.

Toast API have couple of default templates as you can see from the enum below.
public enum ToastTemplateType
{
ToastImageAndText01 = 0,
ToastImageAndText02 = 1,
ToastImageAndText03 = 2,
ToastImageAndText04 = 3,
ToastSmallImageAndText01 = 4,
ToastSmallImageAndText02 = 5,
ToastSmallImageAndText03 = 6,
ToastSmallImageAndText04 = 7,
ToastText01 = 8,
ToastText02 = 9,
ToastText03 = 10,
ToastText04 = 11,
}
Before you can call the Toast from your code you need to make sure the “Toast Capable” is set to Yes in your “Package.appxmanifest” file.

The below code define a Toast template with Image and Text.
void DisplayToastWithImage()
{
// GetTemplateContent returns a Windows.Data.Xml.Dom.XmlDocument
// object containing the toast XML
XmlDocument toastXml = ToastNotificationManager.
GetTemplateContent(ToastTemplateType.ToastImageAndText01);
// You can use the methods from the XML document to specify all of the
// required parameters for the toast
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
XmlElement imageElement = (XmlElement)imageElements.Item(0);
imageElement.SetAttribute("src", "package://images\\Winner.png");
imageElement.SetAttribute("alt", "Placeholder image");
XmlNodeList textElements = toastXml.GetElementsByTagName("text");
for (uint i = 0; i < textElements.Length; i++)
{
textElements.Item(i).AppendChild
(toastXml.CreateTextNode("Congratulations You Won"));
}
// Create a toast from the Xml, then create a ToastNotifier object
// to show the toast
ToastNotification toast = new ToastNotification(toastXml);
// If you have other applications in your package, you can specify
// the AppId of the app to create a ToastNotifier for that application
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
Step 5: Add Share Support
One of the coolest things in Metro Application is the Contracts API, the Contracts allow you to work with the shell and with other apps using the WinRT.
For Example: if you want to select a local file, or Tweet something you just need to use the Contracts to send the other program the object you want to share.

So first, create an instance of DataTransferManager and implement the DataRequested event.
private DataTransferManager _dataTransferManager;
public MainPage()
{
_dataTransferManager = DataTransferManager.GetForCurrentView();
_dataTransferManager.DataRequested +=
new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>
(_dataTransferManager_DataRequested);
}
In the DataRequested just define what you want to send to the Share Application, you can also send Bitmap and other stuff depends on your application.
In the below example if the user want to share and is still playing I’ll send the application download link, but if the user won the game I’ll send his score.
void _dataTransferManager_DataRequested(DataTransferManager sender,
DataRequestedEventArgs args)
{
args.Request.Data.Properties.Title = "Metro Puzzle";
if (_timer.IsEnabled) // If the user didn't finish the game
{
args.Request.Data.Properties.Description = "Share Metro Application";
args.Request.Data.SetText("Got Windows 8? You Should Download" +
" Metro Puzzle – " + Const.DownloadLink);
}
else
{
args.Request.Data.Properties.Description = "Share Win";
args.Request.Data.SetText(string.Format("I've just finish Metro "+
"Puzzle in {0} moves in {1}, think you can beat me? {2}",
txtMoves.Text, txtTime.Text, Const.DownloadLink));
}
}
You can also force the Share UI to appear on demand using the following method:
DataTransferManager.ShowShareUI();
Download Metro Puzzle
How To Deploy It:
Open the solution in Visual Studio and Compile it, or click the Deploy.bat file.

Enjoy