Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / XAML

And Now for XAML Completely Different

Rate me:
Please Sign up or sign in to vote.
4.92/5 (46 votes)
1 Apr 2010CPOL6 min read 43.4K   397   59  
Using Markup Extensions to build individual markup based declarative systems with XAML
<Main xmlns="clr-namespace:MarkupScript;assembly=MarkupScript">
  
  <!-- A simple integration test. Runs TestClient.xaml and compares the output to the previously recorded text files. 
      If you start this the first time, or if you have modified TestClient, you must run TestRunner with the /Recording switch to record test output.
      From now on you can call TestRunner without arguments to verify that markup script is still working properly.
      -->

  <Main.ArgumentDefinitions>
    <ArgumentDefinitions>
      <!-- Define two switches to control the mode -->
      <SwitchArgument Name="Recording" Description="Prepare a new test set by recording the output."/>
      <SwitchArgument Name="Verbose" Description="Output the test clients console."/>
    </ArgumentDefinitions>
  </Main.ArgumentDefinitions>

  <Main.Variables>
    <Variables>
      <!-- Global variable to count number of failed tests -->
      <Variable Name="NumberOfTestsFailed" Value="0"/>
      <!-- Definition of the tests. A simple two dimensional array. 
          The outer array is the list of tests.
          The inner array is used like a structure to define the parameters of each test.
          -->
      <Variable Name="Tests">
        <Variable.Value>
          <Array>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test1.txt"/>
                  <Variable Name="Input" Value=""/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml"/>
                </Array>
              </Variable.Value>
            </Variable>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test2.txt"/>
                  <Variable Name="Input" Value="abc&#10;"/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml SequentialArg1 /MandatorySwitch=0815"/>
                </Array>
              </Variable.Value>
            </Variable>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test3.txt"/>
                  <Variable Name="Input" Value="7&#10;"/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml SequentialArg1 /MandatorySwitch=0815 /OptionalSwitch" />
                </Array>
              </Variable.Value>
            </Variable>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test4.txt"/>
                  <Variable Name="Input" Value="1&#10;"/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml SequentialArg1 SequentialArg2 /MandatorySwitch=0815"/>
                </Array>
              </Variable.Value>
            </Variable>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test5.txt"/>
                  <Variable Name="Input" Value="X&#10;"/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml SequentialArg1 SequentialArg2 SequentialArg3 /MandatorySwitch=0815"/>
                </Array>
              </Variable.Value>
            </Variable>
            <Variable>
              <Variable.Value>
                <Array>
                  <Variable Name="OutputFileName" Value="Scripts\Test6.txt"/>
                  <Variable Name="Input" Value="X&#10;"/>
                  <Variable Name="Arguments" Value="Scripts\TestClient.xaml SequentialArg1 /InvalidSwitch /MandatorySwitch=0815"/>
                </Array>
              </Variable.Value>
            </Variable>
          </Array>
        </Variable.Value>
      </Variable>
    </Variables>
  </Main.Variables>

  <Main.Functions>
    <Functions>
      <!-- 
        A simple function taking two parameters, a file name and the output of the test script.
        In recording mode it simply writes the output to the file. 
        In test mode it compares the content of the file to the output.
      -->
      <Function Name="CheckResult">
        <!-- 
          The programms arguments are stored in the array named "Arguments". 
          A valueless switch is True if it's on the command line and False otherwise. 
        -->
        <If Condition="{Get Arguments, Member=Recording}">
          <!-- Recording => write output to file. -->
          <Write FileName="{Get FileName}" Value="{Get Output}"/>
          <If.Else>
            <!-- Testing => compare file content to output. -->
            <If Condition="{Equal Left={Read FileName={Get FileName}}, Right={Get Output}}">
              <Echo Text="Test Succeeded."/>
              <If Condition="{Get Arguments, Member=Verbose}">
                <Echo Text="{Get Output}"/>
              </If>
              <If.Else>
                <Scope>
                  <Echo Text="Test Failed!"/>
                  <Echo Text="{Get Output}"/>
                  <!-- 
                    Increment global variable NumberOfTestsFailed. 
                    The variable must be passed by reference, since the increment statement needs to modify it. 
                  -->
                  <Increment Variable="{Ref NumberOfTestsFailed}"/>
                </Scope>
              </If.Else>
            </If>
          </If.Else>
        </If>
      </Function>
    </Functions>
  </Main.Functions>
  
  <!-- "Body" or entry point of the main function. The program starts here. -->
  
  <!-- Loop over the "Tests" array. The current loop value will be stored in the local variable "Test" -->
  <ForEach Variable="Test" In="{Get Tests}">
    <ForEach.Variables>
      <Variables>
        <!-- Define local variable to receive the output of the test client. -->
        <Variable Name="RedirectedOutput"/>
      </Variables>
    </ForEach.Variables>
    <!-- Run the script engine with the arguments and input for the current test. Redirect the output into our local variable "RedirectedOutput" -->
    <Shell FileName="MarkupScript.exe" Arguments="{Get Test, Member=Arguments}" StdIn="{Get Test, Member=Input}" StdOut="{Ref RedirectedOutput}"/>
    <!-- 
      Now call the "CheckResult" function with the arguments file name and output. 
    -->
    <Call Function="CheckResult">
      <Argument Name="FileName" Value="{Get Test, Member=OutputFileName}"/>
      <Argument Name="Output" Value="{Get RedirectedOutput}"/>
    </Call>
  </ForEach>

  <!-- Now that all tests have been executed, check if any test has failed and output the appropriate message. -->
  <If Condition="{Equal Left=0, Right={Get NumberOfTestsFailed}}">
    <Echo Text="All tests passed!"/>
    <If.Else>
      <Scope>
        <Write Value="{Get NumberOfTestsFailed}"/>
        <WriteLine Value=" Tests failed!"/>
      </Scope>
    </If.Else>
  </If>

  <!-- Done. Wait until the user presses any key. -->
  <Pause/>

</Main>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions