当所选选项上下文参数不存在时,在 Visual Studio 2013 webtest 中抑制 WebTestException

Suppress WebTestException in Visual Studio 2013 webtest when Selected Option context parameter not exist

在 Visual Studio 2013 WebTest 中,我使用 "Selected Option" 提取规则将 DropDown 的值提取到上下文参数中。只要 selected 选项存在,它就可以正常工作。如果 selected 选项不存在(在我的测试中完全可以接受),测试会抛出异常,"The select tag 'SuchAndSuch' was not found."

错误消息具有误导性。当我查看响应时,我发现 select 标签 "SuchAndSuch" 确实存在,只是没有 selected 选项。也就是说,这个Html标签存在:

<select name="SuchAndSuch">

但它没有这样的子标签:

<option selected="selected">

我还尝试使用 "Extract Attribute Value" 提取规则在下拉列表中提取 selected 项,因为后一个规则具有 "Required" 属性.

规则是查找具有属性 "selected=selected," 的标记 "option" 的第一个实例,然后提取 "value" 属性的值。我有 "Required" false 因为这个下拉列表不会总是有 selected 项目。

我的Extract Attribute Value规则的属性如下:

<RuleParameters>
        <RuleParameter Name="TagName" Value="option" />
        <RuleParameter Name="AttributeName" Value="value" />
        <RuleParameter Name="MatchAttributeName" Value="selected" />
        <RuleParameter Name="MatchAttributeValue" Value="selected" />
        <RuleParameter Name="HtmlDecode" Value="True" />
        <RuleParameter Name="Required" Value="False" />
        <RuleParameter Name="Index" Value="0" />
</RuleParameters>

只要下拉菜单包含 selected 项目,此方法就可以正常工作。如果没有,WebTest 将抛出 WebTestException

Context Parameter 'SuchAndSuch' not found in test context

请求没有执行。

我想要的行为是当这个特定的下拉列表缺少一个 selected 项目时我希望那个特定的请求继续执行并且我希望测试不记录 WebTestException。这可能吗?

本例的答案是编写自定义提取规则:https://msdn.microsoft.com/en-us/library/ms243179(v=vs.120).aspx

下面是我自己创建的规则,它基于我从这里窃取的代码:https://social.msdn.microsoft.com/Forums/en-US/df4f2a0b-2fc4-4d27-9380-ac80100ca0b7/need-help-with-complex-extraction-rule?forum=vstswebtest

我首先在与 webtest 相同的项目中创建规则。当我 运行 网络测试时,它在尝试加载提取规则时立即出错并出现 "FileNotFound" 异常。我将提取规则移动到一个单独的项目并从 Web 测试项目中引用它,它解决了那个问题。

[DisplayName("Extract Single-Select Dropdown")]
    [Description("Extracts the attribute value of AttributeName from the selected option if selected option exists.")]
    public class ExtractSingleSelectDropdown : ExtractionRule
    {
        [Description("The 'name' attribute of the rendered 'select' tag.")]
        public string DropdownName { get; set; }
        [Description("The name of the attribute of the rendered 'option' tag that contains the value that is extracted to the Context Parameter.")]
        public string OptionAttributeName { get; set; }
        [Description("When true, sets Success 'false' if a selected option is not found.")]
        public bool Required { get; set; }

        public override void Extract(object sender, ExtractionEventArgs e)
        {
            if (e.Response.HtmlDocument != null)
            {
                var tags = e.Response.HtmlDocument.GetFilteredHtmlTags(new string[] { "select", "option" });
                if (tags != null && tags.Count() > 0)
                {
                    //find the first <select><option selected="selected"> tag
                    var selectedOption = tags.SkipWhile(tag => String.IsNullOrWhiteSpace(tag.GetAttributeValueAsString("name")) || !tag.GetAttributeValueAsString("name").Equals(this.DropdownName, StringComparison.InvariantCultureIgnoreCase)) // skip tags that aren't the select tag we're looking for
                        .Skip(1) // skip the <select> tag
                        .TakeWhile(tag => tag.Name.Equals("option"))
                        .Where(tag => String.IsNullOrWhiteSpace(tag.GetAttributeValueAsString("selected"))) //
                        .FirstOrDefault();

                    if (selectedOption == null)
                    {
                        e.Message = string.Format("Zero selected options in Dropdown {0}", DropdownName);
                        e.WebTest.Context[ContextParameterName] = string.Empty;
                        e.Success = (this.Required ? false : true);
                    }
                    else
                    {
                        e.WebTest.Context[ContextParameterName] = selectedOption.GetAttributeValueAsString(OptionAttributeName);
                        e.Success = true;
                    }
                }
            }
        }
    }