public void NewAnimated_Returns_PageAndImage() { var stub = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null //в этом тесте новых страниц нет, поэтому первый селектор вернет null }; IPageSelector pageSelectorForNewPages = stub; //а главную "роль" в тесте исполнит селектор новых аним.изображений - он должен вернуть AnimatedImage animatedImage = new AnimatedImage { BlobName = "code-geass:img1.gif", TweetDate = null //гифка новая даты твита не должно быть }; var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = new AnimatedImage[] { animatedImage } //стаб вернет этот результат }; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; //в этом тесте ожидается работа стаба FindPageByBlobNameStub - он должен "найти" страницу по имени блоба SitePage page = new SitePage { URL = "https://dummy/code-geass" }; var findPageByBlob = new Stubs.FindPageByBlobNameStub { DontThrowNotImpl = true, Result = page }; //имитируем найденную страницу... IFindPageByBlobName findPageByBlobName = findPageByBlob; IPageSelector pageSelectorForAnyPages = new Stubs.PageSelectorStub(); IFindAnimatedByPage findAnimatedByPage = new Stubs.FindAnimatedByPageStub(); IPageOrExternalImageSelector pageOrExternalImageSelector = new Stubs.PageOrExternalImageSelectorStub(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; //проверяем что он вернул Assert.IsNotNull(result); Assert.IsNotNull(result.Page); Assert.IsNotNull(result.Image); //для поиска должны передать строго то имя блоба, что мы предусмотрели тестом Assert.IsTrue(findPageByBlob.UsedBlobNameForFind == animatedImage.BlobName); Assert.AreSame(page, result.Page); Assert.AreSame(animatedImage, result.Image); }
public void NewPageFound_Returns_This_Page() { SitePage page = new SitePage { URL = "https://dummy/url" }; //pageSelectorForNewPages в данном тесте имеет осмысленную реализацию и выдает всегда одну страницу var stub = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = page }; IPageSelector pageSelectorForNewPages = stub; IFindAnimatedByPage animatedSelectorForNewImages = new Stubs.AnimatedSelectorStub(); IPageSelector pageSelectorForAnyPages = new Stubs.PageSelectorStub(); IFindAnimatedByPage findAnimatedByPage = new Stubs.FindAnimatedByPageStub(); IPageOrExternalImageSelector pageOrExternalImageSelector = new Stubs.PageOrExternalImageSelectorStub(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; //проверяем что он вернул Assert.IsNotNull(result); Assert.IsNotNull(result.Page); Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image"); Assert.AreSame(page, result.Page); }
void _PageFoundBody(AnimatedImage[] resultForFindAnimated) { SitePage page = new SitePage { URL = "https://dummy/url" }; //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц) var stubNewPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null }; //этот стаб вернет null (нет новых аним.изображений) var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = null }; IPageSelector pageSelectorForNewPages = stubNewPages; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub(); var stubAnyPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = page }; //Главный "герой" этого теста - должен вернуть одну страницу (ее когда-то твитили, но уже давно) IPageSelector pageSelectorForAnyPages = stubAnyPages; //в нашем тесте этот универсальный поиск выдает null (нет аним.изображений для страницы) var stubFindAnimated = new Stubs.FindAnimatedByPageStub { DontThrowNotImpl = true, Result = resultForFindAnimated }; IFindAnimatedByPage findAnimatedByPage = stubFindAnimated; IPageOrExternalImageSelector pageOrExternalImageSelector = new Stubs.PageOrExternalImageSelectorStub(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; //проверяем что он вернул Assert.IsNotNull(result); Assert.IsNotNull(result.Page); Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image"); Assert.AreSame(page, result.Page); }
public void NewAnimated_FindPageByBlobName_Returns_Null_Exception() { var stub = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null //в этом тесте новых страниц нет, поэтому первый селектор вернет null }; IPageSelector pageSelectorForNewPages = stub; //это часть урла, а блоб всегда содержит в начале такое же (до двоеточия) string codeGeassURLPart = "code-geass"; //а главную "роль" в тесте исполнит селектор новых аним.изображений - он должен вернуть AnimatedImage animatedImage = new AnimatedImage { BlobName = "code-geass:img1.gif", TweetDate = null //гифка новая даты твита не должно быть }; var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = new AnimatedImage[] { animatedImage } //стаб вернет этот результат }; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; //в этом тесте ожидается работа стаба FindPageByBlobNameStub - он должен НЕ найти страницу по имени блоба (вернуть null) //и это приведет в итоге к исключению var findPageByBlob = new Stubs.FindPageByBlobNameStub { DontThrowNotImpl = true, Result = null }; //имитируем найденную страницу... IFindPageByBlobName findPageByBlobName = findPageByBlob; IPageSelector pageSelectorForAnyPages = new Stubs.PageSelectorStub(); IFindAnimatedByPage findAnimatedByPage = new Stubs.FindAnimatedByPageStub(); IPageOrExternalImageSelector pageOrExternalImageSelector = new Stubs.PageOrExternalImageSelectorStub(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); try { TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; } catch (AggregateException aggrEx) { ApplicationException appEx = (ApplicationException)aggrEx.InnerExceptions[0]; //это и должно было произойти. В тексте наш спец.текст Assert.IsTrue(appEx.Message.Contains("Find page by blob name failed for")); Assert.IsTrue(appEx.Message.Contains(codeGeassURLPart)); } }
public void No_Page_For_Twitting() { //этот аналог важен для покрытия кода var stubNewPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null }; //этот стаб вернет null (нет новых аним.изображений) var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = null }; IPageSelector pageSelectorForNewPages = stubNewPages; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub(); var stubAnyPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null //Это ситуация которую моделирует тест - такое не должно быть в реальной системе (и будет выброс исключения) }; IPageSelector pageSelectorForAnyPages = stubAnyPages; //в нашем тесте этот универсальный поиск выдает null (нет аним.изображений для страницы) var stubFindAnimated = new Stubs.FindAnimatedByPageStub { DontThrowNotImpl = true, Result = null }; IFindAnimatedByPage findAnimatedByPage = stubFindAnimated; IPageOrExternalImageSelector pageOrExternalImageSelector = new Stubs.PageOrExternalImageSelectorStub(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); try { TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; Assert.Fail("Ожидался выброс исключения ApplicationException так как селектор pageSelectorForAnyPages вернул null (чего быть в работе не должно никогда)"); } catch (System.AggregateException aggrEx) { ApplicationException appEx = (ApplicationException)aggrEx.InnerExceptions[0]; //это и должно было произойти. В тексте наш спец.текст Assert.IsTrue(appEx.Message.Contains("No page found for twitting")); } }
public void PageFound_And_AnimatedFound_Random_Select_PageOnly() { //Тест-кейс: найдена не-новая страница и у нее есть внешние изображения. Рандомизированный выбор "решил" что их не нужно использовать SitePage page = new SitePage { URL = "https://dummy/url" }; //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц) var stubNewPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null }; //этот стаб вернет null (нет новых аним.изображений) var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = null }; IPageSelector pageSelectorForNewPages = stubNewPages; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub(); var stubAnyPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = page }; //Главный "герой" этого теста - должен вернуть одну страницу (ее когда-то твитили, но уже давно) IPageSelector pageSelectorForAnyPages = stubAnyPages; //аним.изображения найдены, но их не будем использовать AnimatedImage[] animatedImgs = new AnimatedImage[] { //здесь нам не важно что - оно просто должно быть, тест "не выбирает" это new AnimatedImage() { BlobName = "dummy", TweetDate = new DateTime(2020, 04, 26, 00, 00, 00) } }; var stubFindAnimated = new Stubs.FindAnimatedByPageStub { DontThrowNotImpl = true, Result = animatedImgs }; IFindAnimatedByPage findAnimatedByPage = stubFindAnimated; //этот стаб имитирует "случайное решение" о том использовать ли изобр.со страницы , или внешнее анимированное. //В этом тесте он всегда выбирает "со страницы" var stubRandomPageOrImg = new Stubs.PageOrExternalImageSelectorStub(); stubRandomPageOrImg.DontThrowNotImpl = true; stubRandomPageOrImg.UseExternalAnimatedImage = false; //именно это важно для данного теста IPageOrExternalImageSelector pageOrExternalImageSelector = stubRandomPageOrImg; IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new Stubs.AnimatedSelectorWithExcludeLastStub(); var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; //проверяем что он вернул Assert.IsNotNull(result); Assert.IsNotNull(result.Page); Assert.IsNull(result.Image, "Не очікувалося заповнення TwittData.Image"); Assert.AreSame(page, result.Page); }
public void PageFound_And_AnimatedFound_Random_Select_Animated() { //Тест-кейс: найдена не-новая страница и у нее есть внешние изображения. Рандомизированный выбор "решил" использовать одно из них SitePage page = new SitePage { URL = "https://kawaii-mobile.com/oregairu" }; //pageSelectorForNewPages в данном тесте выдает null чтобы логика прошла дальше (нет новых страниц) var stubNewPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = null }; //этот стаб вернет null (нет новых аним.изображений) var animNewStub = new Stubs.AnimatedSelectorStub { DontThrowNotImpl = true, Result = null }; IPageSelector pageSelectorForNewPages = stubNewPages; IFindAnimatedByPage animatedSelectorForNewImages = animNewStub; IFindPageByBlobName findPageByBlobName = new Stubs.FindPageByBlobNameStub(); var stubAnyPages = new Stubs.PageSelectorStub { DontThrowNotImpl = true, Result = page }; IPageSelector pageSelectorForAnyPages = stubAnyPages; var anim1 = new AnimatedImage { BlobName = "oregairu:img1.gif", TweetDate = new DateTime(2020, 04, 26, 00, 00, 00) }; var anim2 = new AnimatedImage { BlobName = "oregairu:yukinoshita.gif", TweetDate = new DateTime(2020, 01, 10, 22, 10, 00) }; var anim3 = new AnimatedImage { BlobName = "oregairu:hatiman.gif", TweetDate = new DateTime(2020, 02, 08, 08, 00, 00) }; //аним.изображения найдены, тест использует всегда одно из них (anim2) AnimatedImage[] animatedImgs = new AnimatedImage[] { anim1, anim2, anim3 }; var stubFindAnimated = new Stubs.FindAnimatedByPageStub { DontThrowNotImpl = true, Result = animatedImgs }; IFindAnimatedByPage findAnimatedByPage = stubFindAnimated; //этот стаб имитирует "случайное решение" о том использовать ли изобр.со страницы , или внешнее анимированное. //В этом тесте он всегда выбирает "со страницы" var stubRandomPageOrImg = new Stubs.PageOrExternalImageSelectorStub(); stubRandomPageOrImg.DontThrowNotImpl = true; stubRandomPageOrImg.UseExternalAnimatedImage = true; //именно это важно для данного теста IPageOrExternalImageSelector pageOrExternalImageSelector = stubRandomPageOrImg; var animSelectorStub = new Stubs.AnimatedSelectorWithExcludeLastStub { DontThrowNotImpl = true, Result = anim2 }; IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = animSelectorStub; var pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, animatedSelectorForNewImages, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, new TweetCreator.Stubs.Logger()); TwittData result = pageForTwittingSelector.GetPageForTwitting().Result; //проверяем что он вернул Assert.IsNotNull(result); Assert.IsNotNull(result.Page); //в тесте ожидается что вернут и изображение что мы указали Assert.IsNotNull(result.Image); Assert.AreSame(result.Image, anim2); Assert.AreSame(page, result.Page); }
public static async Task Run([TimerTrigger("0 0 * * * *")] TimerInfo timer, ILogger log) { //https://docs.microsoft.com/ru-ru/azure/azure-functions/functions-bindings-timer?tabs=csharp#ncrontab-expressions //0 */5 * * * * - каждые 5 мин //"0 0 * * * *" - каждый час Logger logger = new Logger(log); logger.Log($"TweetPostFunction executed at: {DateTime.Now}"); string animatedBlobConnectionString = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_azure_animatedblob"); string azureSiteDBConnectionString = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_azure_sitepages"); if (string.IsNullOrEmpty(animatedBlobConnectionString)) { logger.LogError("animatedBlobConnectionString not found!"); return; } if (string.IsNullOrEmpty(azureSiteDBConnectionString)) { logger.LogError("azureSiteDBConnectionString not found!"); return; } IDatabase database = new Database(azureSiteDBConnectionString, true, null); logger.Log($"database connected: {DateTime.Now}"); //если в переменных задано что "не обновлять индексы", то мы сэкономим время работы в прод-окружении - индексы создаются один раз, //и дальше и так работают, хотя MongoDB и говорит что "нет проблем". //Если будет нужно обновлять индексы, или будет новое окружение (новая база, коллекция и прочее) то эту переменную среды надо убрать. //А когда все настроено и уже работает, ее можно создать для общего ускорения string dontCreateIndexesStr = kawaii.twitter.core.Env.EnvironmentSecureData.GetValueFromEnvironment("env:kawaii_twitter_dont_create_indexes"); bool dontCreateIndexes = false; if (!string.IsNullOrEmpty(dontCreateIndexesStr)) { bool.TryParse(dontCreateIndexesStr, out dontCreateIndexes); } if (dontCreateIndexes) { logger.Log("Indexes will not updated (found env:kawaii_twitter_dont_create_indexes)"); } AnimatedImageCollection animatedImageCollection = new AnimatedImageCollection(database, null, !dontCreateIndexes); var imagesCollection = animatedImageCollection.AnimatedImages; logger.Log($"imagesCollection init done: {DateTime.Now}"); SitePageCollection sitePageCollection = new SitePageCollection(database, null, !dontCreateIndexes); var sitePagesCollection = sitePageCollection.SitePages; logger.Log($"sitePagesCollection init done: {DateTime.Now}"); ITwitterTextCreator textCreator = new kawaii.twitter.core.Text.TwitterTextCreator(); IImageOnWeb imageOnWeb = new kawaii.twitter.core.HtmlParsers.ImageOnWeb(_HttpClient); ITwitterImageURL twitterImageURL = new kawaii.twitter.core.HtmlParsers.TwitterImageURL(_HttpClient); //--- блок для lastTweetUpdater var dateSupply = new kawaii.twitter.core.Env.DateSupply(); IAnimatedTweetDateUpdater animatedTweetDateUpdater = new AnimatedTweetDateUpdater(imagesCollection); ISitePageTweetDateUpdater sitePageTweetDateUpdater = new SitePageTweetDateUpdater(sitePagesCollection); ILastTweetUpdater lastTweetUpdater = new kawaii.twitter.core.SelectLogic.LastTweetUpdater(dateSupply, animatedTweetDateUpdater, sitePageTweetDateUpdater); //--- //сервису твиттера нужно передать авториз.данные var service = new kawaii.twitter.core.TwitterService.Service(); var animatedImagesBlobContainer = new AnimatedImagesBlobContainer(animatedBlobConnectionString); IBlobDownload blobDownload = animatedImagesBlobContainer; var randomSelector = new kawaii.twitter.core.SelectLogic.Randomize.RandomSelector(); int topQueryCount = 10; ISpecialDaySelector specialDaySelector = new SpecialDaySelector(dateSupply, randomSelector); string specialDayName = specialDaySelector.DetectSpecialDayName(); IFolderFromURL folderFromURL = new kawaii.twitter.core.SelectLogic.URL.FolderFromURL(); var formatter = new kawaii.twitter.core.SelectLogic.BlobName.Formatter(); IPageSelector pageSelectorForNewPages = new kawaii.twitter.core.SelectLogic.Page.NotTwittedPages(sitePagesCollection, randomSelector, specialDayName, topQueryCount); IFindAnimatedByPage findNewAnimatedByPage = new kawaii.twitter.core.SelectLogic.Images.Newly.NotTwittedAnimated(imagesCollection, randomSelector, topQueryCount, folderFromURL, formatter); IPageSelector pageSelectorForAnyPages = new kawaii.twitter.core.SelectLogic.Page.PageSelector(sitePagesCollection, randomSelector, specialDayName, topQueryCount); IFindAnimatedByPage findAnimatedByPage = new kawaii.twitter.core.SelectLogic.Images.Find.FindAnimatedByPage(imagesCollection.AsQueryable(), folderFromURL, formatter); IPageOrExternalImageSelector pageOrExternalImageSelector = new kawaii.twitter.core.SelectLogic.PageOrExternalImage.PageOrExternalImageSelector(); IAnimatedSelectorWithExcludeLast animatedSelectorWithExcludeLast = new kawaii.twitter.core.SelectLogic.Images.ExcludeUsed.AnimatedSelectorWithExcludeLast(); IPageForTwittingSelector pageForTwittingSelector = new kawaii.twitter.core.SelectLogic.PageForTwittingSelector(pageSelectorForNewPages, findNewAnimatedByPage, pageSelectorForAnyPages, findAnimatedByPage, pageOrExternalImageSelector, animatedSelectorWithExcludeLast, logger); var tweetCreator = new kawaii.twitter.core.TweetCreator(pageForTwittingSelector, textCreator, twitterImageURL, imageOnWeb, blobDownload, service, lastTweetUpdater, logger); logger.Log($"tweetCreator.Execute: {DateTime.Now}"); //выполнить твит заданной страницы и изображения await tweetCreator.Execute(); }