瀏覽代碼

Add specific tests for output, with mocks (still WIP)

theenglishway (time) 7 年之前
父節點
當前提交
814beee52f

+ 222 - 0
tests/fixtures/tweets/link_10.yaml

@@ -0,0 +1,222 @@
+- !!python/object:twhatter.parser.user.User
+  followers_nb: 10
+  following_nb: 30
+  id: 943804775942033408
+  join_date: 2017-12-21 00:00:00
+  likes_nb: 17
+  screen_name: theenglishway
+  soup: null
+  tweets_nb: 83
+
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [GrandDebat]
+  id: 1087059470621048836
+  likes_nb: 0
+  link_to: https://t.co/1u1pmVm2oI
+  media: null
+  mention_list: [596420812]
+  permalink: /the_english_way/status/1087059470621048836
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Vu dans le dernier @canardenchaine, le remplacement dans 2 r\xE9gions de\
+    \ l'enqu\xEAte publique pour les projets environnementaux par une consultation\
+    \ par voie \xE9l\xE9ctronique \xE0 fins \"d'exp\xE9rimentation\". Le #GrandDebat\
+    \ avant l'heurehttps://www.lemoniteur.fr/article/suppression-de-l-enquete-publique-dans-le-cadre-de-l-autorisation-environnementale-donnez-votre-avis.2006719\_\
+    \u2026"
+  timestamp: 2019-01-20 18:49:09
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog, AffaireBenalla]
+  id: 1085843193885851648
+  likes_nb: 1
+  link_to: https://t.co/05PluIG3Mp
+  media: null
+  mention_list: [155948847]
+  permalink: /the_english_way/status/1085843193885851648
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 2
+  screen_name: the_english_way
+  soup: null
+  text: "Nouvel article sur mon #blog : un r\xE9sum\xE9 qui se veut objectif des auditions\
+    \ d'hier dans l'#AffaireBenalla (mais n'y parvient pas). Et un grand merci au\
+    \ @Senat de nous proposer des discussions d'une si grande qualit\xE9.https://blog.theenglishway.eu/fr/auditions-senat-0.html#auditions-senat-0\_\
+    \u2026"
+  timestamp: 2019-01-17 10:16:06
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 2
+  hashtag_list: []
+  id: 1077505613079429120
+  likes_nb: 1
+  link_to: https://t.co/el5VJucLRz
+  media: null
+  mention_list: []
+  permalink: /the_english_way/status/1077505613079429120
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 1
+  screen_name: the_english_way
+  soup: null
+  text: "Le p\xE8re No\xEBl, un bon exemple de socialisme compar\xE9 \xE0 la petite\
+    \ souris ou \xE0 Halloween ? :Dhttps://jacobinmag.com/2018/12/santa-claus-socialism-christmas\_\
+    \u2026"
+  timestamp: 2018-12-25 10:05:31
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog]
+  id: 1060480082987356161
+  likes_nb: 0
+  link_to: https://t.co/kUgDRV2btD
+  media: null
+  mention_list: []
+  permalink: /the_english_way/status/1060480082987356161
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Nouvel article sur mon #blog :https://blog.theenglishway.eu/la-gratuite.html#la-gratuite\_\
+    \u2026"
+  timestamp: 2018-11-08 10:32:09
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: []
+  id: 1052565222316285957
+  likes_nb: 0
+  link_to: https://t.co/y0ictRW5TM
+  media: null
+  mention_list: [106443426]
+  permalink: /the_english_way/status/1052565222316285957
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Journal de bord, entr\xE9e #1 : http://blog.theenglishway.eu/log-001.html\_\
+    \n(ou aussi : @CCI_Paris_IdF c'est bien!)"
+  timestamp: 2018-10-17 14:21:19
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog]
+  id: 1037399737480212480
+  likes_nb: 0
+  link_to: https://t.co/IE1XSeHyZV
+  media: null
+  mention_list: []
+  permalink: /the_english_way/status/1037399737480212480
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Nouvel article sur mon #blog ! \nComment faire un business model qui claque,\
+    \ selon Wall Street, ou \"qu'est ce qui fait la valeur d'une boite selon les investisseurs\"\
+    \ :  http://blog.theenglishway.eu/business-model-wall-street.html\_\u2026  \n\
+    Il y a 10 crit\xE8res, le 6e vous surprendra !"
+  timestamp: 2018-09-05 17:59:06
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog, functionalstupidity]
+  id: 1036172843065790466
+  likes_nb: 0
+  link_to: https://t.co/Nkl5wXUgyT
+  media: null
+  mention_list: [291129749]
+  permalink: /the_english_way/status/1036172843065790466
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "New article on my #blog : functional stupidity, or how our work-places drive\
+    \ us into stupidity (introducing Mats Alvesson and @andre_spicer 's book on #functionalstupidity)http://blog.theenglishway.eu/en/functional-stupidity-0.html\_\
+    \u2026"
+  timestamp: 2018-09-02 08:43:51
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog]
+  id: 1036172317443989505
+  likes_nb: 1
+  link_to: https://t.co/2aA4v3fhgO
+  media: null
+  mention_list: [291129749]
+  permalink: /the_english_way/status/1036172317443989505
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Nouvel article sur mon #blog : la stupidit\xE9 fonctionelle, ou comment nos\
+    \ environnements de travail nous poussent \xE0 la stupidit\xE9 (introduction au\
+    \ livre de Mats Alvesson & @andre_spicer)http://blog.theenglishway.eu/fr/functional-stupidity-0.html\_\
+    \u2026"
+  timestamp: 2018-09-02 08:41:46
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: []
+  id: 1028882171816275968
+  likes_nb: 0
+  link_to: https://t.co/jCDJSndUhC
+  media: null
+  mention_list: []
+  permalink: /the_english_way/status/1028882171816275968
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "Article miniature sur Alan Turing :http://blog.theenglishway.eu/alan-turing.html\_\
+    \u2026"
+  timestamp: 2018-08-13 05:53:20
+  user_id: 943804775942033408
+- !!python/object:twhatter.parser.tweet.TweetLink
+  comments_nb: 0
+  hashtag_list: [blog]
+  id: 1027798020174372865
+  likes_nb: 0
+  link_to: https://t.co/dgT75s80VJ
+  media: null
+  mention_list: [20404918]
+  permalink: /the_english_way/status/1027798020174372865
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 0
+  screen_name: the_english_way
+  soup: null
+  text: "And now for something completely different ! First dive into @sqlalchemy\
+    \ #bloghttp://blog.theenglishway.eu/en/sqlalchemy-intro.html\_\u2026"
+  timestamp: 2018-08-10 06:05:18
+  user_id: 943804775942033408
+

+ 193 - 0
tests/fixtures/tweets/reaction_9.yaml

@@ -0,0 +1,193 @@
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 350
+  hashtag_list: [ActeX]
+  id: 1086603899186880512
+  likes_nb: 3413
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086603899186880512
+  reacted_id: 1086556426074578945
+  reacted_user_id: 29955464
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 2348
+  screen_name: davduf
+  soup: null
+  text: "La fatigue nerveuse, la pression, le renversement m\xE9diatique soudain,\
+    \ le d\xE9ni politique qui s'acharne, et puis les larmes. \n\nEt aujourd'hui,\
+    \ #ActeX.  Pas question de l\xE2cher @Place_Beauvau \n\nPour vos signalements:\
+    \ email ou DM circonstanci\xE9s svp  http://www.davduf.net/giletsjaunes-et-violencespolicieres-le\_\
+    \u2026https://twitter.com/arretsurimages/status/1086556426074578945\_\u2026"
+  timestamp: 2019-01-19 12:38:52
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 111
+  hashtag_list: []
+  id: 1087111932560244736
+  likes_nb: 1006
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /davduf/status/1087111932560244736
+  reacted_id: 1087073778545246208
+  reacted_user_id: 338985020
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 582
+  screen_name: davduf
+  soup: null
+  text: "\xABOn ne peut pas demander aux manifestants d'\xEAtre exemplaires si on\
+    \ ne l'est pas soi-m\xEAme \xBB, a estim\xE9 dimanche le porte-parole du gouvernement,\
+    \ Benjamin Griveaux, apr\xE8s la mise en cause de l'utilisation de lanceurs de\
+    \ balles de d\xE9fense (LBD) par la police.\n\nOn avance.https://twitter.com/afpfr/status/1087073778545246208\_\
+    \u2026"
+  timestamp: 2019-01-20 22:17:36
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 16
+  hashtag_list: []
+  id: 1087053227227578369
+  likes_nb: 217
+  link_to: null
+  media: null
+  mention_list: [160534877]
+  permalink: /davduf/status/1087053227227578369
+  reacted_id: 1087043032350973958
+  reacted_user_id: 12786782
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 201
+  screen_name: davduf
+  soup: null
+  text: "Rectificatif: les images sont sign\xE9es @ClementLanot (dont le travail est\
+    \ remarquable)  https://www.youtube.com/watch?v=fDugakictUw\_\u2026 ( \xE0 27mn11s)https://twitter.com/davduf/status/1087043032350973958\_\
+    \u2026"
+  timestamp: 2019-01-20 18:24:20
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 39
+  hashtag_list: []
+  id: 1086946146398945281
+  likes_nb: 332
+  link_to: null
+  media: null
+  mention_list: [13353862]
+  permalink: /davduf/status/1086946146398945281
+  reacted_id: 1086879785530331141
+  reacted_user_id: 13353862
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 100
+  screen_name: davduf
+  soup: null
+  text: "Les commentaires sur le fil Twitter de @LEXPRESS sont charmants comme un\
+    \ dimanche matin.https://twitter.com/LEXPRESS/status/1086879785530331141\_\u2026"
+  timestamp: 2019-01-20 11:18:50
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 3
+  hashtag_list: [ActeX, Montepellier, LBD40]
+  id: 1086779719599747072
+  likes_nb: 103
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086779719599747072
+  reacted_id: 1086770685471531008
+  reacted_user_id: 2973410193
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 158
+  screen_name: davduf
+  soup: null
+  text: "allo @Place_Beauvau - c'est pour un signalement - 325 (pr\xE9cisions)\n\n\
+    #ActeX #Montepellier #LBD40https://twitter.com/OctavieMrl/status/1086770685471531008\_\
+    \u2026"
+  timestamp: 2019-01-20 00:17:31
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 5
+  hashtag_list: [ActeX, Montepellier, LBD40]
+  id: 1086779578918584321
+  likes_nb: 153
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086779578918584321
+  reacted_id: 1086774517647790080
+  reacted_user_id: 2973410193
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 264
+  screen_name: davduf
+  soup: null
+  text: "allo @Place_Beauvau - c'est pour un signalement - 326 (pr\xE9cisions)\n\n\
+    #ActeX #Montepellier #LBD40https://twitter.com/OctavieMrl/status/1086774517647790080\_\
+    \u2026"
+  timestamp: 2019-01-20 00:16:57
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 7
+  hashtag_list: [LBD40, Montepellier, ActeX]
+  id: 1086707919138234369
+  likes_nb: 154
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086707919138234369
+  reacted_id: 1086692368835923969
+  reacted_user_id: 2973410193
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 264
+  screen_name: davduf
+  soup: null
+  text: "allo @Place_Beauvau - c'est pour un signalement - 331\n\nTir de #LBD40 dans\
+    \ les fesses\n\n#Montepellier, #ActeXhttps://twitter.com/OctavieMrl/status/1086692368835923969\_\
+    \u2026"
+  timestamp: 2019-01-19 19:32:12
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 38
+  hashtag_list: [Rennes, ActeX]
+  id: 1086689891851882496
+  likes_nb: 840
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086689891851882496
+  reacted_id: 1086657757351165952
+  reacted_user_id: 594686101
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 1094
+  screen_name: davduf
+  soup: null
+  text: "allo @Place_Beauvau - c'est pour un signalement - 329\n\nGaz lacrymog\xE8\
+    nes malgr\xE9 un passant au sol. Malaise cardiaque. \n\nNon assistance \xE0 personne\
+    \ en danger. \nArticle 223-6 du code P\xE9nal.\n\n#Rennes, #ActeXhttps://twitter.com/SamuelNohra/status/1086657757351165952\_\
+    \u2026"
+  timestamp: 2019-01-19 18:20:34
+  user_id: 12786782
+- !!python/object:twhatter.parser.tweet.TweetReaction
+  comments_nb: 6
+  hashtag_list: [LBD40, ActeX]
+  id: 1086672423553064961
+  likes_nb: 204
+  link_to: null
+  media: null
+  mention_list: [62747302]
+  permalink: /davduf/status/1086672423553064961
+  reacted_id: 1086666326981201920
+  reacted_user_id: 8350912
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 343
+  screen_name: davduf
+  soup: null
+  text: "allo @Place_Beauvau - c'est pour un signalement - 327\n\n#LBD40, jambe droite\
+    \ sur vid\xE9aste\n\nParis, #ActeXhttps://twitter.com/Le_Figaro/status/1086666326981201920\_\
+    \u2026"
+  timestamp: 2019-01-19 17:11:09
+  user_id: 12786782

+ 205 - 0
tests/fixtures/tweets/retweet_10.yaml

@@ -0,0 +1,205 @@
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 724
+  hashtag_list: [FilmTwitter]
+  id: 1072503598372638720
+  likes_nb: 4089
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /TwitterMovies/status/1072503598372638720
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1072583629258309632
+  retweeter: Twitter
+  retweets_nb: 802
+  screen_name: TwitterMovies
+  soup: null
+  text: "#FilmTwitter, you get to decide what the ultimate holiday movie is.\n \n\
+    12/11  Round 1 \n12/12  Semi-Final \n12/13  Final\n12/14  Winner Crowned \n\n\
+    Round 1 starts in the thread below.pic.twitter.com/Uy4MfMK2Ew"
+  timestamp: 2018-12-11 14:49:18
+  user_id: 436266454
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 2474
+  hashtag_list: [ThisHappened]
+  id: 1070274641594327041
+  likes_nb: 534808
+  link_to: null
+  media: null
+  mention_list: [335141638]
+  permalink: /TwitterMusic/status/1070274641594327041
+  reacted_id: 1070272742849687553
+  reacted_user_id: 1526228120
+  retweet_id: 1070337144504365057
+  retweeter: Twitter
+  retweets_nb: 182492
+  screen_name: TwitterMusic
+  soup: null
+  text: "You did it ARMY. @BTS_twt was the most Tweeted about in 2018. \n\nMore music\
+    \ facts in the thread below. Yep, #ThisHappenedhttps://twitter.com/TwitterData/status/1070272742849687553\_\
+    \u2026"
+  timestamp: 2018-12-05 11:12:13
+  user_id: 373471064
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 727
+  hashtag_list: []
+  id: 986643494499438592
+  likes_nb: 35480
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /StephenKing/status/986643494499438592
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1063100430719180802
+  retweeter: Twitter
+  retweets_nb: 7095
+  screen_name: StephenKing
+  soup: null
+  text: Graffiti is the Twitter of the streets.
+  timestamp: 2018-04-18 16:31:54
+  user_id: 2233154425
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 127
+  hashtag_list: []
+  id: 1060331216434577409
+  likes_nb: 12788
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /holly/status/1060331216434577409
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1060694382020452352
+  retweeter: Twitter
+  retweets_nb: 3577
+  screen_name: holly
+  soup: null
+  text: 'There are two social networks: Twitter, and all the ones that post screenshots
+    of posts from Twitter'
+  timestamp: 2018-11-08 00:40:36
+  user_id: 7555262
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 141
+  hashtag_list: [HappyDeepavali]
+  id: 1060087039369068544
+  likes_nb: 2744
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /TwitterIndia/status/1060087039369068544
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1060202167657742336
+  retweeter: Twitter
+  retweets_nb: 368
+  screen_name: TwitterIndia
+  soup: null
+  text: 'We wish everyone who''s celebrating the festival of lights a very #HappyDeepavali
+    May you and your family have a wonderful year ahead!'
+  timestamp: 2018-11-07 08:30:20
+  user_id: 103770785
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 265
+  hashtag_list: [BeAVoter]
+  id: 1058023358032371712
+  likes_nb: 1950
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /TwitterGov/status/1058023358032371712
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1058094152062304257
+  retweeter: Twitter
+  retweets_nb: 573
+  screen_name: TwitterGov
+  soup: null
+  text: 'Election Day in the US is right around the corner. Everyone, including these
+    people you may know, wants you to show up to the polls.
+
+
+    Make your voice heard in the US election and #BeAVoter.pic.twitter.com/vxfh3l9J3d'
+  timestamp: 2018-11-01 15:50:00
+  user_id: 222953824
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 320
+  hashtag_list: []
+  id: 1057860310143508480
+  likes_nb: 39435
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /lilyachty/status/1057860310143508480
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1058014225585631233
+  retweeter: Twitter
+  retweets_nb: 8779
+  screen_name: lilyachty
+  soup: null
+  text: Yo twitter just might be the best place of all time
+  timestamp: 2018-11-01 05:02:06
+  user_id: 175198393
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 1795
+  hashtag_list: []
+  id: 1057675174735155200
+  likes_nb: 15065
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /TwitterSafety/status/1057675174735155200
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1057678634004217856
+  retweeter: Twitter
+  retweets_nb: 3710
+  screen_name: TwitterSafety
+  soup: null
+  text: "Activity that attempts to manipulate or disrupt Twitter\u2019s service is\
+    \ not allowed. We remove this when we see it.\n\nYou can now specify what type\
+    \ of spam you're seeing when you report, including fake accounts.pic.twitter.com/GN9NKw2Qyn"
+  timestamp: 2018-10-31 16:46:26
+  user_id: 95731075
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 125
+  hashtag_list: []
+  id: 1057290498203926528
+  likes_nb: 2438
+  link_to: null
+  media: !!python/object:twhatter.parser.media.MediaImage
+    image_links: ['https://pbs.twimg.com/media/DqxAEiEUwAAuajU.jpg']
+    soup: null
+  mention_list: []
+  permalink: /TwitterData/status/1057290498203926528
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1057363608764592133
+  retweeter: Twitter
+  retweets_nb: 579
+  screen_name: TwitterData
+  soup: null
+  text: "r u abbreving less rn? \n\nSince the switch to 280 characters a year ago,\
+    \ we've seen an increase in people writing out full words and phrases.pic.twitter.com/pjnfyVmilY"
+  timestamp: 2018-10-30 15:17:52
+  user_id: 1526228120
+- !!python/object:twhatter.parser.tweet.TweetRetweet
+  comments_nb: 4656
+  hashtag_list: []
+  id: 1055221967048060928
+  likes_nb: 138890
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /ArianaGrande/status/1055221967048060928
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: 1055232863933612033
+  retweeter: Twitter
+  retweets_nb: 21301
+  screen_name: ArianaGrande
+  soup: null
+  text: i love retweeting my own tweets
+  timestamp: 2018-10-24 22:18:16
+  user_id: 34507480

+ 201 - 0
tests/fixtures/tweets/text_only_10.yaml

@@ -0,0 +1,201 @@
+- !!python/object:twhatter.parser.user.User
+  followers_nb: 55903189
+  following_nb: 140
+  id: 783214
+  join_date: 2007-02-20 00:00:00
+  likes_nb: 5590
+  screen_name: Twitter
+  soup: null
+  tweets_nb: 8706
+
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 970
+  hashtag_list: []
+  id: 1087225139538862080
+  likes_nb: 16305
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1087225139538862080
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 2423
+  screen_name: Twitter
+  soup: null
+  text: ''
+  timestamp: 2019-01-21 05:47:27
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 3446
+  hashtag_list: []
+  id: 1087059835370328064
+  likes_nb: 52960
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1087059835370328064
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 7850
+  screen_name: Twitter
+  soup: null
+  text: Tweeting...
+  timestamp: 2019-01-20 18:50:36
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 1269
+  hashtag_list: []
+  id: 1086379213349769216
+  likes_nb: 34958
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1086379213349769216
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 6117
+  screen_name: Twitter
+  soup: null
+  text: Weekends spark joy
+  timestamp: 2019-01-18 21:46:03
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 15775
+  hashtag_list: []
+  id: 1085915351605424128
+  likes_nb: 49578
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1085915351605424128
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 4849
+  screen_name: Twitter
+  soup: null
+  text: You. In emojis.
+  timestamp: 2019-01-17 15:02:49
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 3352
+  hashtag_list: [TriggersMeIn4Words]
+  id: 1085718564286345217
+  likes_nb: 39887
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1085718564286345217
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 7958
+  screen_name: Twitter
+  soup: null
+  text: 'Your edit button requests #TriggersMeIn4Words'
+  timestamp: 2019-01-17 02:00:52
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 3502
+  hashtag_list: []
+  id: 1085569366358257664
+  likes_nb: 77065
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1085569366358257664
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 20527
+  screen_name: Twitter
+  soup: null
+  text: You got this
+  timestamp: 2019-01-16 16:08:00
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 553
+  hashtag_list: []
+  id: 1085265146644058112
+  likes_nb: 4255
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1085265146644058112
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 1060
+  screen_name: Twitter
+  soup: null
+  text: Android, we got you. Starting today, tap  to switch between latest and top
+    Tweets.pic.twitter.com/7rXo3BNEJ6
+  timestamp: 2019-01-15 19:59:08
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 3320
+  hashtag_list: []
+  id: 1084982024794861568
+  likes_nb: 48030
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1084982024794861568
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 8234
+  screen_name: Twitter
+  soup: null
+  text: brb
+  timestamp: 2019-01-15 01:14:07
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 9137
+  hashtag_list: []
+  id: 1083581799467442177
+  likes_nb: 138039
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1083581799467442177
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 36589
+  screen_name: Twitter
+  soup: null
+  text: Go to sleep
+  timestamp: 2019-01-11 04:30:07
+  user_id: 783214
+- !!python/object:twhatter.parser.tweet.TweetTextOnly
+  comments_nb: 9685
+  hashtag_list: []
+  id: 1082713943200751616
+  likes_nb: 175003
+  link_to: null
+  media: null
+  mention_list: []
+  permalink: /Twitter/status/1082713943200751616
+  reacted_id: null
+  reacted_user_id: null
+  retweet_id: null
+  retweeter: null
+  retweets_nb: 55540
+  screen_name: Twitter
+  soup: null
+  text: Hahahahahahahaha
+  timestamp: 2019-01-08 19:01:34
+  user_id: 783214

+ 0 - 0
tests/output/__init__.py


+ 64 - 0
tests/output/conftest.py

@@ -0,0 +1,64 @@
+import yaml
+import pytest
+
+from twhatter.parser import TweetBase, User
+
+@pytest.fixture(scope="session")
+def fixtures_factory():
+    """Factory for any kind of data that can be stored in YAML format"""
+    def _fixtures_factory(yaml_file):
+        with open(yaml_file, 'r') as f:
+            fixtures = yaml.load(f)
+        return fixtures
+
+    return _fixtures_factory
+
+
+@pytest.fixture(scope="session")
+def tweets_factory(fixtures_factory):
+    """Factory for tweets from YAML file"""
+    def _tweets_factory(yaml_file):
+        all_fixtures = fixtures_factory(yaml_file)
+        return [t for t in all_fixtures if isinstance(t, TweetBase)]
+
+    return _tweets_factory
+
+
+@pytest.fixture(scope="session")
+def users_factory(fixtures_factory):
+    """Factory for tweets from YAML file"""
+    def _users_factory(yaml_file):
+        all_fixtures = fixtures_factory(yaml_file)
+        return [u for u in all_fixtures if isinstance(u, User)]
+
+    return _users_factory
+
+@pytest.fixture
+def timeline_mock_factory(tweets_factory, monkeypatch, timeline_attribute):
+    def _timeline_mock_factory(tweets_file):
+        tweets = tweets_factory(tweets_file)
+
+        class MockClientTimeline:
+            def __init__(self, user, limit):
+                pass
+
+            def __iter__(self):
+                return iter(tweets)
+        monkeypatch.setattr(timeline_attribute, MockClientTimeline)
+
+    return _timeline_mock_factory
+
+@pytest.fixture
+def profile_mock_factory(users_factory, monkeypatch, profile_attribute):
+    def _profile_mock_factory(user_file):
+        users = users_factory(user_file)
+
+        # Make a dictionary out of users, indexed by the twitter handle
+
+        class MockClientProfile:
+            def __init__(self, user):
+                if user in users:
+                    self.user = users[user]
+
+        monkeypatch.setattr(profile_attribute,  MockClientProfile)
+    return _profile_mock_factory

+ 27 - 0
tests/output/test_print.py

@@ -0,0 +1,27 @@
+import pytest
+from twhatter.output import Print
+
+@pytest.fixture
+def timeline_attribute():
+    return "twhatter.output.print.ClientTimeline"
+
+@pytest.fixture
+def profile_attribute():
+    return "twhatter.output.print.ClientProfile"
+
+@pytest.fixture
+def output():
+    return Print()
+
+@pytest.mark.parametrize("fixtures_file, expected_len", [
+    ('tests/fixtures/tweets/text_only_10.yaml', 10),
+    ('tests/fixtures/tweets/retweet_10.yaml', 10),
+    ('tests/fixtures/tweets/link_10.yaml', 10),
+    ('tests/fixtures/tweets/reaction_9.yaml', 9),
+])
+def test_output_tweets(capsys, timeline_mock_factory, output, fixtures_file, expected_len):
+    timeline_mock_factory(fixtures_file)
+    output.output_tweets(None, None)
+
+    captured = capsys.readouterr()
+    assert len(captured.out.split('\n')) == expected_len + 1