public void Expansion_Basic() { var actualGreetings = new List <string>(); // First we'll create some config using the "DymeConfig" class... var testConfig = DymeConfig.New("HelloWorld") .AddProperty("Name", "Ali") .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }); // Then we'll automatically generate our test cases using the "TestCaseLoader" class... var testCases = DymeCaseLoader.CasesFromConfig(testConfig); // Now we can extract the data from our test cases and use it to make friends... foreach (var testCase in testCases) { var greeting = testCase["Name"] + " says " + testCase["Greeting"]; Debug.WriteLine(greeting); actualGreetings.Add(greeting); } // Just to make sure that we're saying the right stuff... var expectedGreetings = new[] { "Ali says Hello World", "Ali says Bonjour le monde", }; // Lets double check the data that we generated from our test cases... CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
public void PoolProperties_GivenBuriedInConfig_AppropriateUsage() { // Arrange... var config1 = DymeConfig.New("TestConfig1") .AddProperty("b", new[] { "1", "2" }, ExpansionTypeEnum.pool); var config2 = DymeConfig.New("TestConfig2") .AddProperty("IMPORT", "TestConfig1") .AddProperty("a", new[] { "1", "2", "3", "4" }); var expectedCases = new[] { "p:a(1) p:b(1)", "p:a(2) p:b(2)", "p:a(3) p:b(1)", "p:a(4) p:b(2)" }; // Act... var testCases = DymeCaseLoader.CasesFromConfig(config2, new [] { config1 }); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void ResolveSetup_2DefaultSetupsWithExpandedProperties() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("D[1]") .AddProperty("a", new[] { "1", "2", "3" }) .AddProperty("b", "1"), DymeConfig.New("D[2]") .AddProperty("a", new[] { "4", "5" }) .AddProperty("c", "1") }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.DefaultSetup", new[] { "D[1]" }) .AddProperty("IMPORT.DefaultSetup2", new[] { "D[2]" }) .AddProperty("d", "1"); var expectedCases = new[] { "p:a(4) p:b(1) p:c(1) p:d(1)", "p:a(5) p:b(1) p:c(1) p:d(1)" }; // Act... var testCases = new DymeCaseLoader().CasesFromConfigs(testConfig, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public IEnumerable <DymeCase> CasesFromConfigs(DymeConfig mainConfig, IEnumerable <DymeConfig> configLibrary) { var postApplyConfigProperties = new List <DymeConfigProperty>(); /// Ensure config naming and structure... var namedConfigLibrary = configLibrary.Select(c => c.ConfigWithNameFromConfigWithNameProperty(_regexMatchForSpecialPropertyConfigName)); mainConfig = mainConfig.ConfigWithNameFromConfigWithNameProperty(_regexMatchForSpecialPropertyConfigName); /// Get relevant configs from library... var relevantConfigLibrary = GetRelevantConfigsFromLibrary(mainConfig, namedConfigLibrary); /// Pre-Process library configs (extract post-apply-cases)... postApplyConfigProperties.AddRange(PreProcessConfigAndReturnPostApplyConfigs(mainConfig, out DymeConfig processedMainConfig)); var processedConfigLibrary = new List <DymeConfig>(); foreach (var libraryConfig in relevantConfigLibrary) { postApplyConfigProperties.AddRange(PreProcessConfigAndReturnPostApplyConfigs(libraryConfig, out DymeConfig processedLibraryConfig)); processedConfigLibrary.Add(processedLibraryConfig); } /// Convert configs to node tree... var nodeTree = NodeTreeFromConfigs(mainConfig, processedConfigLibrary); /// Convert node tree to cases... var cases = CasesFromNodeTree(nodeTree); ///Apply post-apply-cases... var finalCases = CreatePoolProperties(cases, postApplyConfigProperties); return(finalCases.ToList()); }
public void ExpandSetup_GivenPermutationSet_Expect4Permutations() { // Arrange... var configLibrary = new List <DymeConfig>(); var config = DymeConfig.New("TestConfig") .AddProperty("a", new[] { "1", "2" }) .AddProperty("b", new[] { "1", "2" }) .AddProperty("c", "1"); var expectedCases = new[] { "p:a(1) p:b(1) p:c(1)", "p:a(1) p:b(2) p:c(1)", "p:a(2) p:b(1) p:c(1)", "p:a(2) p:b(2) p:c(1)" }; // Act... var testCases = new DymeCaseLoader().CasesFromConfigs(config, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); Assert.AreEqual(4, testCases.Count()); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
internal Node NodeTreeFromConfigs(DymeConfig config, IEnumerable <DymeConfig> configLibrary) { var configNodeTree = new Node(config.Name, NodeTypeEnum.ValueNode); configNodeTree.Children = PropertyNodesFromConfig(config, configLibrary).Select(n => n as Node).ToList(); return(configNodeTree); }
public void Pooling_Basic() { var actualGreetings = new List <string>(); // Define all the people that will be greeting. We don't care to much about what they say so we'll use a pool property to give them some greetings... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new[] { "Ali", "Bernice", "Chi", "David" }) .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }, ExpansionTypeEnum.pool); // Generate the test cases... var testCases = DymeCaseLoader.CasesFromConfig(people); // Extract the data from our new test cases... foreach (var testCase in testCases) { var finalGreeting = testCase["Name"] + " says " + testCase["Greeting"]; Debug.WriteLine(finalGreeting); actualGreetings.Add(finalGreeting); } // Just to make sure that we have the right stuff... var expectedGreetings = new[] { "Ali says Hello World", "Bernice says Bonjour le monde", "Chi says Hello World", "David says Bonjour le monde", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
public void ResolveSetup_3DefaultSetups2LevelsDeepWithExpansionsReversePriority() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("D[1]") .AddProperty("a", "1"), DymeConfig.New("D[2]") .AddProperty("a", new[] { "2.1", "2.2" }), DymeConfig.New("D[3]") .AddProperty("IMPORT.DefaultSetup", "D[2]") }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.DefaultSetup", "D[3]") .AddProperty("IMPORT.DefaultSetup2", new[] { "D[1]" }); var expectedCases = new[] { "p:a(1)", }; // Act... var testCases = new DymeCaseLoader().CasesFromConfigs(testConfig, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void ResolveSetup_1ExpandedDefaultSetupsEachWith2ExpandedProperties() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("D[1]") .AddProperty("a", new[] { "T", "F" }), DymeConfig.New("D[2]") .AddProperty("b", new[] { "T", "F" }) }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.DefaultSetup", new[] { "D[1]", "D[2]" }) .AddProperty("c", new[] { "T", "F" }); var expectedCases = new[] { "p:a(T) p:c(T)", "p:a(T) p:c(F)", "p:a(F) p:c(T)", "p:a(F) p:c(F)", "p:b(T) p:c(T)", "p:b(T) p:c(F)", "p:b(F) p:c(T)", "p:b(F) p:c(F)" }; // Act... var testCases = new DymeCaseLoader().CasesFromConfigs(testConfig, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void ResolveSetup() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("D[1]") .AddProperty("a", "1") }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.DefaultSetup", "D[1]") .AddProperty("b", "1"); var expectedCases = new[] { "p:a(1) p:b(1)" }; // Act... var testCases = new DymeCaseLoader().CasesFromConfigs(testConfig, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void CorrelationComposedConfigAndField() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("Composition1") .AddProperty("a", "1"), DymeConfig.New("Composition2") .AddProperty("a", "2"), }; var config = DymeConfig.New("Super") .AddProperty("IMPORT", new[] { "Composition1", "Composition2" }, "correlationKeyX") .AddProperty("c", new[] { "1", "2" }, "correlationKeyX"); var expectedCases = new[] { "p:a(1) p:c(1)", "p:a(2) p:c(2)" }; // Act... var testCases = DymeCaseLoader.CasesFromConfig(config, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); Assert.AreEqual(2, testCases.Count()); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void CorrelationImportedConfigs() { // Arrange... var configLibrary = new List <DymeConfig>() { DymeConfig.New("TestConfig1") .AddProperty("a", new[] { "1", "2" }, "correlationKey") }; var config = DymeConfig.New("TestConfig2") .AddProperty("IMPORT", "TestConfig1") .AddProperty("b", new[] { "1", "2" }, "correlationKey"); var expectedCases = new[] { "p:a(1) p:b(1)", "p:a(2) p:b(2)" }; // Act... var testCases = DymeCaseLoader.CasesFromConfig(config, configLibrary); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); Assert.AreEqual(2, testCases.Count()); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public IEnumerable <DymeCase> CasesFromConfigs(DymeConfig config) { var configLibrary = new List <DymeConfig>() { }; return(CasesFromConfigs(config, configLibrary)); }
public void Correlation_Basic() { var actualGreetings = new List <string>(); // Lets define some people properties with multiple values, and then correlate those properties using a correlation key... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new[] { "Ali Mire", "Bernice Newton" }, "someKey") .AddProperty("Age", new[] { "40", "35" }, "someKey") .AddProperty("Gender", new[] { "male", "female" }, "someKey"); // ..."someKey" will work fine here, but in larger or more complex config structures, you may want to consider using a GUID.. // Next we'll pull those people into our greeting config... var greetings = DymeConfig.New("GreetingConfig") .AddProperty("IMPORT", "PeopleConfig") .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }); // We'll create a library of configs... var configLibrary = new[] { people }; //...and pass it in along with the config that we want to interpret... var testCases = DymeCaseLoader.CasesFromConfig(greetings, configLibrary); //...(the passed in config library is used to resolve any "IMPORT" references) // Extract the data from our new test cases... foreach (var testCase in testCases) { var name = testCase["Name"]; var age = testCase["Age"]; var gender = testCase["Gender"]; var greeting = testCase["Greeting"]; var finalGreeting = $"{name} (a {age} year old {gender}) says {greeting}"; Debug.WriteLine(finalGreeting); actualGreetings.Add(finalGreeting); } // Just to make sure that we have the right stuff... var expectedGreetings = new[] { "Ali Mire (a 40 year old male) says Hello World", "Ali Mire (a 40 year old male) says Bonjour le monde", "Bernice Newton (a 35 year old female) says Hello World", "Bernice Newton (a 35 year old female) says Bonjour le monde", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); // Make sure that we don't have any of the wrong stuff... var antiGreetings = new List <string> { "Ali Mire (a 40 year old female) says Hello World", "Ali Mire (a 35 year old male) says Bonjour le monde", "Ali Mire (a 35 year old female) says Bonjour le monde", "Bernice Newton (a 35 year old male) says Hello World", "Bernice Newton (a 40 year old female) says Bonjour le monde", "Bernice Newton (a 40 year old male) says Bonjour le monde", }; antiGreetings.ForEach(antiGreeting => CollectionAssert.DoesNotContain(actualGreetings, antiGreeting)); }
public void CasesFromConfigs_GivenInheritingDeviceSetups_ExpectTestCase() { // Arrange... var sut = new DymeCaseLoader(); var configLibrary = new List <DymeConfig> { DymeConfig.New("DeviceFarm") .AddProperty("Selenium.Hub.Url", "http://SuperStack/hub") .AddProperty("API.Key", "1234") .AddProperty("Username", "JakeDyme"), DymeConfig.New("IPhone8") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: appiumVersion", "1.13.0") .AddProperty("Capability: deviceName", "iPhone 8 Simulator") .AddProperty("Capability: deviceOrientation", "portrait") .AddProperty("Capability: platformVersion", "12.2") .AddProperty("Capability: platformName", "iOS") .AddProperty("Capability: browserName", "Safari"), DymeConfig.New("Android") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: appiumVersion", "1.9.0") .AddProperty("Capability: deviceName", "Android Emulator") .AddProperty("Capability: deviceOrientation", "portrait") .AddProperty("Capability: platformVersion", "8.0") .AddProperty("Capability: platformName", "Android") .AddProperty("Capability: browserName", "Chrome"), DymeConfig.New("Windows10Desktop") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: browserVersion", "54.0") .AddProperty("Capability: platformName", "Windows 10") .AddProperty("Capability: browserName", "firefox"), DymeConfig.New("Sites") .AddProperty("Domain", new [] { "google", "ebay", "amazon" }, "urls&domains") .AddProperty("Url", new[] { "https://www.google.com/search?p=", "http://www.ebay.com/sch/", "https://www.amazon.com/" }, "urls&domains") .AddProperty("Criteria", new[] { "laptop", "playstation" }) }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.Devices", new[] { "IPhone8", "Android", "Windows10Desktop" }) .AddProperty("IMPORT.Sites", "Sites"); // Act... var testCases = sut.CasesFromConfigs(testConfig, configLibrary); // Assert... foreach (var testCase in testCases) { var url = testCase["Url"]; var criteria = testCase["Criteria"]; var domain = testCase["Domain"]; _driver.Url = $"{url}/{criteria}"; SaveScreenshot(domain, "Screenshot"); } }
public void Composition_WithEncapsulation() { var actualGreetings = new List <string>(); var ali = DymeConfig.New("AliConfig") .AddProperty("Greeting", new[] { "Goodbuy", "Bon achat" }) .AddProperty("Name", new[] { "Ali", "Brian" }); var bernice = DymeConfig.New("BerniceConfig") .AddProperty("Greeting", "What?") .AddProperty("Name", new[] { "Ali", "Brian" }); var greetings = DymeConfig.New("GreetingConfig") .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }); // Create a config composed of many configs... var composedConfig = DymeConfig.New("ComposedConfig") .AddProperty("IMPORT.People", new[] { "AliConfig", "BerniceConfig" }) //...using an optional suffix (.People) for readability .AddProperty("IMPORT", "GreetingConfig"); // Note: the property "Greeting" from "GreetingConfig" will override "Greeting" from "PeopleConfig" // because "GreetingConfig" is imported after "PeopleConfig" in "ComposedConfig" // Create a config library of configs... var configLibrary = new[] { ali, bernice, greetings }; //...and pass it in along with the config that we want to interpret... var testCases = DymeCaseLoader.CasesFromConfig(composedConfig, configLibrary); // Extract the data from our test cases, and use it to start a family... foreach (var testCase in testCases) { var greeting = testCase["Name"] + " says " + testCase["Greeting"]; Debug.WriteLine(greeting); actualGreetings.Add(greeting); } // Just to make sure that we're saying the right stuff... var expectedGreetings = new[] { "Ali says Hello World", "Ali says Bonjour le monde", "Brian says Hello World", "Brian says Bonjour le monde", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); // Make sure we don't have any of the wrong stuff... var antiGreetings = new List <string> { "Ali says Goodbuy", "Ali says Goodbuy", "Ali says Bon achat", "Ali says Bon achat", }; antiGreetings.ForEach(antiGreeting => CollectionAssert.DoesNotContain(actualGreetings, antiGreeting)); }
public void Pooling_WithCorrelation() { var actualGreetings = new List <string>(); // Define some people that will be greeting, and supply a greetings pool to pick from, // but also specify an explicit correlation key on the pool itself... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new[] { "Ali", "Bernice", "Chi", "David" }) .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }, ExpansionTypeEnum.pool, "petSounds"); // ...Humans will get greetings even though they are not explicitly correlated // because they originate from the same config (PeopleConfig). // Pets normally wouldn't use the human greetings because the greetings are encapsulated in the human config, // but because we've specified a correlation between them (petSounds), // the Pets will now get access to the greetings despite encapsulation. var pets = DymeConfig.New("PetsConfig") .AddProperty("Name", new[] { "Alpha-Dog", "Mini-Mouse", "Curious-Cat" }, "petSounds"); var main = DymeConfig.New("MainConfig") .AddProperty("IMPORT.Organisms", new[] { "PeopleConfig", "PetsConfig" }); // Create config library... var configLibrary = new[] { people, pets, main }; // Generate the test cases... var testCases = DymeCaseLoader.CasesFromConfig(main, configLibrary); // Extract the data from our new test cases... foreach (var testCase in testCases) { var name = testCase["Name"]; var greeting = testCase.Has("Greeting") ? testCase["Greeting"] : "nothing"; var finalGreeting = $"{name} says {greeting}"; Debug.WriteLine(finalGreeting); actualGreetings.Add(finalGreeting); } // Just to make sure that we have the right stuff... var expectedGreetings = new[] { /// People stuff... "Ali says Hello World", "Bernice says Bonjour le monde", "Chi says Hello World", "David says Bonjour le monde", /// Pet stuff... "Alpha-Dog says Hello World", "Mini-Mouse says Bonjour le monde", "Curious-Cat says Hello World", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
public void Pooling_WithEncapsulation() { var actualGreetings = new List <string>(); // Define some people that will be greeting, and supply greetings pool to pick from... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new[] { "Ali", "Bernice", "Chi", "David" }) .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }, ExpansionTypeEnum.pool); // Pets won't use the human greetings because they're encapsulated in the human config. // Instead pets will use their own encapsulated greeting, which uses correlation instead... var pets = DymeConfig.New("PetsConfig") .AddProperty("Name", new[] { "Alpha-Dog", "Mini-Mouse", "Curious-Cat" }, "petSounds") .AddProperty("Greeting", new[] { "Woof", "Squeek", "Meeow" }, "petSounds"); // ...This also demonstrates that with encapsulation, you can have two different behaviours for the same property. var main = DymeConfig.New("MainConfig") .AddProperty("IMPORT.Organisms", new[] { "PeopleConfig", "PetsConfig" }); // Create config library... var configLibrary = new[] { people, pets, main }; // Generate the test cases... var testCases = DymeCaseLoader.CasesFromConfig(main, configLibrary); // Extract the data from our new test cases... foreach (var testCase in testCases) { var name = testCase["Name"]; var greeting = testCase.Has("Greeting") ? testCase["Greeting"] : "nothing"; var finalGreeting = $"{name} says {greeting}"; Debug.WriteLine(finalGreeting); actualGreetings.Add(finalGreeting); } // Just to make sure that we have the right stuff... var expectedGreetings = new[] { /// People stuff... "Ali says Hello World", "Bernice says Bonjour le monde", "Chi says Hello World", "David says Bonjour le monde", /// Pet stuff... "Alpha-Dog says Woof", "Mini-Mouse says Squeek", "Curious-Cat says Meeow", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
internal IEnumerable <PropertyNode> PropertyNodesFromConfig(DymeConfig parentConfig, IEnumerable <DymeConfig> configLibrary) { var propertyNodes = new List <PropertyNode>(); for (var i = 0; i < parentConfig.Properties.Count(); i++) { var prop = parentConfig.Properties.ElementAt(i); var newPropertyNode = new PropertyNode(prop.Name, NodeTypeEnum.PropertyNode, prop.CorrelationKey); newPropertyNode.Children = LeafNodesFromConfigProperty(configLibrary, prop).Select(n => n as Node).ToList(); newPropertyNode.ValueIndex = i; propertyNodes.Add(newPropertyNode); } return(propertyNodes); }
public static DymeConfig ConfigWithNameFromConfigWithNameProperty(this DymeConfig config, string nameProperty = null) { if (nameProperty == null) { return(config); } Regex match = new Regex(nameProperty); var configNameProp = config.Properties.SingleOrDefault(p => match.IsMatch(p.Name)); if (configNameProp == null) { throw new FormatException($"A config is missing the mandatory identifier property: \"{nameProperty}\". Config: {config.Name ?? config.ToString()}"); } var otherProps = config.Properties.Where(p => !match.IsMatch(p.Name)); return(new DymeConfig(configNameProp.Name, otherProps)); }
/// <summary> /// Extract only the configs that are actually used in config tree... /// </summary> /// <param name="config"></param> /// <param name="receedingConfigLibrary" description="a list that gets its values removed as they are processed in order to make subsequent queries on the list more efficient"></param> /// <returns></returns> private IEnumerable <DymeConfig> GetRelevantConfigsFromLibrary(DymeConfig config, IEnumerable <DymeConfig> configLibrary) { var importConfigNames = GetImportTypeConfigProperties(config).SelectMany(prop => prop.Values); var importedConfigs = new List <DymeConfig>(); foreach (var configName in importConfigNames) { var importedConfig = GetConfigFromLibrary(configName, configLibrary); if (importedConfigs.Any(c => c.Name == importedConfig.Name)) { continue; } importedConfigs.Add(importedConfig); var importedChildConfigs = GetRelevantConfigsFromLibrary(importedConfig, configLibrary) .Where(cc => !importedConfigs.Any(childConfig => childConfig.Name == cc.Name)); importedConfigs.AddRange(importedChildConfigs); } return(importedConfigs); }
public void Pooling_WithComposition() { var actualGreetings = new List <string>(); // Define all the people that will be greeting. We don't care to much about what they say so we'll use a pool property to give them some greetings... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new[] { "Ali", "Bernice", "Chi", "David" }); var greetings = DymeConfig.New("GreetingConfig") .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }, ExpansionTypeEnum.pool); // Create a composition... var main = DymeConfig.New("MainConfig") .AddProperty("IMPORT", "PeopleConfig") .AddProperty("IMPORT", "GreetingConfig"); // We'll create a library of configs... var configLibrary = new[] { people, greetings }; // Generate the test cases... var testCases = DymeCaseLoader.CasesFromConfig(main, configLibrary); // Extract the data from our new test cases... foreach (var testCase in testCases) { var name = testCase["Name"]; var greeting = testCase["Greeting"]; var finalGreeting = $"{name} says {greeting}"; Debug.WriteLine(finalGreeting); actualGreetings.Add(finalGreeting); } // Just to make sure that we have the right stuff... var expectedGreetings = new[] { "Ali says Hello World", "Bernice says Bonjour le monde", "Chi says Hello World", "David says Bonjour le monde", }; CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
public void PoolProperties_GivenMorePoolProperties_ExpectExtraPoolPropertiesAreDropped() { // Arrange... var config = DymeConfig.New("TestConfig") .AddProperty("a", new[] { "1", "2" }) .AddProperty("b", new[] { "1", "2", "3", "4" }, ExpansionTypeEnum.pool); var expectedCases = new[] { "p:a(1) p:b(1)", "p:a(2) p:b(2)" }; // Act... var testCases = DymeCaseLoader.CasesFromConfig(config); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void CorrelationSameConfigs() { // Arrange... var config = DymeConfig.New("TestConfig") .AddProperty("a", new[] { "1", "2" }, "correlationKey") .AddProperty("b", new[] { "1", "2" }, "correlationKey"); var expectedCases = new[] { "p:a(1) p:b(1)", "p:a(2) p:b(2)" }; // Act... var testCases = DymeCaseLoader.CasesFromConfig(config); // Assert var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); CollectionAssert.AreEquivalent(expectedCases, testCaseString); }
public void Inheritence_Basic() { var actualGreetings = new List <string>(); // In this example we want to keep our data separated into neat bundles of related information... // We'll put all person related info into one config... var people = DymeConfig.New("PeopleConfig") .AddProperty("Name", new [] { "Ali", "Brian" }); // ...and all greeting related info into another config. // To bind the data back together, we'll import the people config into the greeting config... var greetings = DymeConfig.New("GreetingConfig") .AddProperty("IMPORT", "PeopleConfig") .AddProperty("Greeting", new[] { "Hello World", "Bonjour le monde" }); // We'll create a library of configs... var configLibrary = new[] { people, greetings }; //...and pass it in along with the config that we want to interpret... var testCases = DymeCaseLoader.CasesFromConfig(greetings, configLibrary); //...(the passed in config library is used to resolve any "IMPORT" references) // Extract the data from our shiny new test cases, and use it to start a party... foreach (var testCase in testCases) { var greeting = testCase["Name"] + " says " + testCase["Greeting"]; Debug.WriteLine(greeting); actualGreetings.Add(greeting); } // Just to make sure that we're saying the right stuff... var expectedGreetings = new[] { "Ali says Hello World", "Ali says Bonjour le monde", "Brian says Hello World", "Brian says Bonjour le monde", }; // Lets double check the data that we generated from our test cases... CollectionAssert.AreEquivalent(expectedGreetings, actualGreetings); }
public void ExpandSetup_GivenPermutationSet_Expect1Permutation() { // Arrange... var configLibrary = new List <DymeConfig>(); var config = DymeConfig.New("TestConfig") .AddProperty("a", "1") .AddProperty("b", "1") .AddProperty("c", "1"); var expectedCases = new[] { "p:a(1) p:b(1) p:c(1)" }; // Act... var nodeTree = new DymeCaseLoader().NodeTreeFromConfigs(config, configLibrary); var testCases = new DymeCaseLoader().CasesFromNodeTree(nodeTree); // Assert... var testCaseString = testCases.Select(tc => new DymeCaseLoader().CaseToString(tc)).ToList(); Assert.AreEqual(expectedCases, testCaseString); }
public void OverThirtyThreeThousandTestCases_Given3ConfigsWith7PropertiesAndASumOf34Values() { // Arrange... var sut = new DymeCaseLoader(); var configLibrary = new List <DymeConfig> { DymeConfig.New("Application") .AddProperty("version", new[] { "1.0", "1.5", "2.0" }), DymeConfig.New("User") .AddProperty("IMPORT", "Application") .AddProperty("user", new[] { "alice", "bob", "cathy", "dave", "eve", "frank", "grant", "harry", "ivan" }), DymeConfig.New("Vehicle") .AddProperty("IMPORT", "User") .AddProperty("make", new[] { "Audi", "Bugatti", "Chrysler", "Dodge", "Ferrari" }) .AddProperty("year", new[] { "2012", "2013", "2014", "2015", "2016" }) .AddProperty("condition", new[] { "new", "used" }) .AddProperty("type", new[] { "convertible", "suv", "4x4", "hatchback", "sudan" }) .AddProperty("feature", new[] { "airbags", "electric_windows", "seat_warmer", "adjustable_steering", "backwiper" }) }; var topLevelConfig = configLibrary.Single(c => c.Name == "Vehicle"); // Act... var testCases = sut.CasesFromConfigs(topLevelConfig, configLibrary); // Assert... var launchUrls = testCases .Select(t => $"http://cars/{t["version"]}/{t["condition"]}/{t["make"]}?user={t["user"]}&year={t["year"]}&with={t["feature"]}&type={t["type"]}") .ToList(); // Check that there are over 33000 test cases... Assert.AreEqual(testCases.Count(), 33750); // Pick some random urls to check that the permutations were created... CollectionAssert.Contains(launchUrls, "http://cars/1.5/new/Dodge?user=harry&year=2013&with=adjustable_steering&type=4x4"); CollectionAssert.Contains(launchUrls, "http://cars/1.0/new/Audi?user=eve&year=2016&with=electric_windows&type=suv"); CollectionAssert.Contains(launchUrls, "http://cars/2.0/used/Ferrari?user=cathy&year=2012&with=airbags&type=sudan"); CollectionAssert.Contains(launchUrls, "http://cars/2.0/used/Chrysler?user=ivan&year=2015&with=backwiper&type=convertible"); }
public void CasesFromConfigs_GivenInheritingDeviceSetups_ExpectTestCase() { // Arrange... var sut = new DymeCaseLoader(); var configLibrary = new List <DymeConfig> { DymeConfig.New("DeviceFarm") .AddProperty("Selenium.Hub.Url", "http://SuperStack/hub") .AddProperty("API.Key", "1234") .AddProperty("Username", "JakeDyme"), DymeConfig.New("IPhone8") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: appiumVersion", "1.13.0") .AddProperty("Capability: deviceName", "iPhone 8 Simulator") .AddProperty("Capability: deviceOrientation", "portrait") .AddProperty("Capability: platformVersion", "12.2") .AddProperty("Capability: platformName", "iOS") .AddProperty("Capability: browserName", "Safari"), DymeConfig.New("Android") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: appiumVersion", "1.9.0") .AddProperty("Capability: deviceName", "Android Emulator") .AddProperty("Capability: deviceOrientation", "portrait") .AddProperty("Capability: platformVersion", "8.0") .AddProperty("Capability: platformName", "Android") .AddProperty("Capability: browserName", "Chrome"), DymeConfig.New("Windows10Desktop") .AddProperty("IMPORT.DeviceFarms", "DeviceFarm") .AddProperty("Capability: browserVersion", "54.0") .AddProperty("Capability: platformName", "Windows 10") .AddProperty("Capability: browserName", "firefox"), DymeConfig.New("Sites") .AddProperty("Domain", new [] { "google", "ebay", "amazon" }, "urls&domains") .AddProperty("Url", new[] { "https://www.google.com/search?p=", "http://www.ebay.com/sch/", "https://www.amazon.com/" }, "urls&domains") .AddProperty("Criteria", new[] { "laptop", "playstation" }) }; var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.Devices", new[] { "IPhone8", "Android", "Windows10Desktop" }) .AddProperty("IMPORT.Sites", "Sites"); // Act... var testCases = sut.CasesFromConfigs(testConfig, configLibrary); // Assert... var actualInstructions = new List <string>(); foreach (var testCase in testCases) { var url = testCase["Url"]; var criteria = testCase["Criteria"]; var domain = testCase["Domain"]; var capabilities = testCase.Properties .Where(prop => prop.Name.StartsWith("Capability: ")) .ToDictionary(prop => prop.Name.Substring(12), prop => prop.Value); actualInstructions.Add($"on {capabilities["platformName"]} device, search for {criteria} on {domain} with url: {url}{criteria}"); } var expectedInstructions = new List <string>() { "on iOS device, search for laptop on google with url: https://www.google.com/search?p=laptop", "on iOS device, search for laptop on ebay with url: http://www.ebay.com/sch/laptop", "on iOS device, search for laptop on amazon with url: https://www.amazon.com/laptop", "on iOS device, search for playstation on google with url: https://www.google.com/search?p=playstation", "on iOS device, search for playstation on ebay with url: http://www.ebay.com/sch/playstation", "on iOS device, search for playstation on amazon with url: https://www.amazon.com/playstation", "on Android device, search for laptop on google with url: https://www.google.com/search?p=laptop", "on Android device, search for laptop on ebay with url: http://www.ebay.com/sch/laptop", "on Android device, search for laptop on amazon with url: https://www.amazon.com/laptop", "on Android device, search for playstation on google with url: https://www.google.com/search?p=playstation", "on Android device, search for playstation on ebay with url: http://www.ebay.com/sch/playstation", "on Android device, search for playstation on amazon with url: https://www.amazon.com/playstation", "on Windows 10 device, search for laptop on google with url: https://www.google.com/search?p=laptop", "on Windows 10 device, search for laptop on ebay with url: http://www.ebay.com/sch/laptop", "on Windows 10 device, search for laptop on amazon with url: https://www.amazon.com/laptop", "on Windows 10 device, search for playstation on google with url: https://www.google.com/search?p=playstation", "on Windows 10 device, search for playstation on ebay with url: http://www.ebay.com/sch/playstation", "on Windows 10 device, search for playstation on amazon with url: https://www.amazon.com/playstation", }; CollectionAssert.AreEquivalent(expectedInstructions, actualInstructions); }
public void Expansion_Example2() { var sut = new DymeCaseLoader(); var configLibrary = new List <DymeConfig> { DymeConfig.New("Places") .AddProperty("Place", new[] { "Statue of Liberty", "Eiffel tower", "Great pyramid of Giza" }), DymeConfig.New("Vocabularies") .AddProperty("IMPORT", "Places") .AddProperty("Language", new[] { "English", "French", "Spanish", "Dutch" }, "x") .AddProperty("Greeting", new[] { "Hello", "Salut", "Hola", "Hallo" }, "x") .AddProperty("Punctuation", "!"), DymeConfig.New("People") .AddProperty("Person", new[] { "Ali", "Brian", "Chien" }) .AddProperty("Positioned", new[] { "standing", "sitting" }), }; var testConfig = DymeConfig.New("HelloWorld") .AddProperty("IMPORT", "People") .AddProperty("IMPORT", "Vocabularies"); var testCases = new DymeCaseLoader().CasesFromConfigs(testConfig, configLibrary); var generatedDataFromTestCases = testCases .Select(tc => $"{tc["Person"]} says {tc["Greeting"]} in {tc["Language"]} while {tc["Positioned"]} on the {tc["Place"]}") .ToList(); // Make sure that we have some of the right stuff... var expectedCollection = new[] { "Ali says Hello in English while sitting on the Statue of Liberty", "Ali says Hello in English while sitting on the Eiffel tower", "Ali says Hello in English while sitting on the Great pyramid of Giza", "Ali says Hello in English while standing on the Statue of Liberty", "Ali says Hello in English while standing on the Eiffel tower", "Ali says Hello in English while standing on the Great pyramid of Giza", "Brian says Hallo in Dutch while sitting on the Statue of Liberty", "Brian says Hallo in Dutch while sitting on the Eiffel tower", "Brian says Hallo in Dutch while sitting on the Great pyramid of Giza", "Brian says Hallo in Dutch while standing on the Statue of Liberty", "Brian says Hallo in Dutch while standing on the Eiffel tower", "Brian says Hallo in Dutch while standing on the Great pyramid of Giza", "Chien says Salut in French while sitting on the Statue of Liberty", "Chien says Salut in French while sitting on the Eiffel tower", "Chien says Salut in French while sitting on the Great pyramid of Giza", "Chien says Salut in French while standing on the Statue of Liberty", "Chien says Salut in French while standing on the Eiffel tower", "Chien says Salut in French while standing on the Great pyramid of Giza", }; CollectionAssert.IsSubsetOf(expectedCollection, generatedDataFromTestCases); // Make sure we dont have any of the wrong stuff... var unexpectedCollection = new List <string> { "Ali says Hello in French while standing on the Great pyramid of Giza", "Brian says Hallo in Spanish while sitting on the Statue of Liberty", "Chien says Salut in English while sitting on the Eiffel tower", }; unexpectedCollection.ForEach(antiGreeting => CollectionAssert.DoesNotContain(generatedDataFromTestCases, antiGreeting)); }
public void CompositionCorrelationInheritenceExpansion() { var actualEvents = new List <string>(); var configLibrary = new List <DymeConfig> { // Device farm details... DymeConfig.New("DeviceFarm") .AddProperty("df.hubUrl", "https://devicefarm.com/hub") .AddProperty("df.login", "JakeD") .AddProperty("df.ApiKey", "SOME+API+KEY"), // Capabilities for an IPhone device... DymeConfig.New("IPhone7") .AddProperty("cap.deviceName", "iPhone 7 Simulator") .AddProperty("cap.appiumVersion", "1.15.0") .AddProperty("cap.deviceOrientation", "portrait") .AddProperty("cap.platformVersion", "13.0") .AddProperty("cap.platformName", "iOS") .AddProperty("cap.browserName", "Safari"), // Capabilities for a Samsung device... DymeConfig.New("SamsungGalaxyS7") .AddProperty("cap.deviceName", "Samsung Galaxy S7 Emulator") .AddProperty("cap.appiumVersion", "1.9.1") .AddProperty("cap.deviceOrientation", "portrait") .AddProperty("cap.platformVersion", "8.1") .AddProperty("cap.platformName", "Android") .AddProperty("cap.browserName", "Chrome") }; // Create a composition config for your test that brings all your information together... var testConfig = DymeConfig.New("TestConfig") .AddProperty("IMPORT.Devices", new[] { "IPhone7", "SamsungGalaxyS7" }) // ...Optional suffixes (eg. ".Devices") can be added to improve readability. .AddProperty("IMPORT.EnvHosts", "DeviceFarm") // ...Trailing imported configs override properties from preceding configs. (.EnvHosts will override any conflicting properties from .Devices) .AddProperty("ApiKey", "USE+THIS+KEY+INSTEAD") //...Top level properties override properties from imported configs. .AddProperty("Url", new [] { "https://www.google.com", "https://www.facebook.com" }, "btn&Url") //...Properties with the same correlation ID will be correlated (by order). .AddProperty("SearchButtonId", new[] { "btnGgleSearch", "fcbkSrchBtn" }, "btn&Url"); //...Correlated properties must have the same number of values (i.e. 2 Urls, 2 button Ids). // Generate test cases... var testCases = DymeCaseLoader.CasesFromConfig(testConfig, configLibrary); //...(the passed in config library is used to resolve any "IMPORT" references) // Extract the data from the test cases, and use it to change the world... foreach (var testCase in testCases) { var url = testCase["Url"]; var btn = testCase["SearchButtonId"]; var loginDetails = getDeviceFarmLoginFromTestCase(testCase); var capabilities = getDeviceDetailsFromTestCase(testCase); var browserInstance = getWebDriverInstance(capabilities, loginDetails); // Perform actions... browserInstance.LaunchUrl(url); browserInstance.ClickOnElement(btn); browserInstance.TakeScreenshot(); // Create validation report... var deviceName = testCase["cap.deviceName"]; actualEvents.Add($"On {deviceName}, launch {url}, and then click {btn}"); } // Make sure that we're doing the right stuff... var expectedEvents = new[] { "On iPhone 7 Simulator, launch https://www.google.com, and then click btnGgleSearch", "On iPhone 7 Simulator, launch https://www.facebook.com, and then click fcbkSrchBtn", "On Samsung Galaxy S7 Emulator, launch https://www.google.com, and then click btnGgleSearch", "On Samsung Galaxy S7 Emulator, launch https://www.facebook.com, and then click fcbkSrchBtn", }; CollectionAssert.AreEquivalent(expectedEvents, actualEvents); // Make sure that we're not doing the wrong stuff... var antiEvents = new List <string> { "On Samsung Galaxy S7 Emulator, launch https://www.google.com, and click fcbkSrchBtn", "On Samsung Galaxy S7 Emulator, launch https://www.facebook.com, and click btnGgleSearch", "On iPhone 7 Simulator, launch https://www.google.com, and click fcbkSrchBtn", "On iPhone 7 Simulator, launch https://www.facebook.com, and click btnGgleSearch", }; antiEvents.ForEach(antiEvent => CollectionAssert.DoesNotContain(actualEvents, antiEvent)); }