Note:
Testo rimosso dalla rev 3 e
Testo aggiunto nella rev4
LunaRss v0.7 – modificat0 da AntonioCarpentieri
Codice LunaRss 0_8 – refactored by XxxMassimiliano
- L’intento di questo refactoring è quello di scrivere il primo test
- Per prima cosa ho racchiuso il codice che utilizza il codice fin qui rifattorizzato in una classe (LunaRss) all’interno di un metodo che ho chiamato Get_Feeds
class LunaRss def Get_Feeds rss_make = RssMaker.new puts rss_make.header feeds.each do |feed| if NEED_PROXY parser = RssParser.new feed, proxy_url else parser = RssParser.new feed end data = parser.esegui_parsing puts rss_make.channel( data.channel ) 0.upto data.titles.length do|i| puts rss_make.entry( data.titles[i], data.descriptions[i], data.links[i] ) end end puts rss_make.footer end end
- Poi ho aggiunto il require della libreria ‘test/unit’ ed ho creato la prima classe di test con un test che fallisce
require 'test/unit' class TestLunaRss < Test::Unit::TestCase def test_this assert_equal true, false end end* ho fatto girare il test e questo è stato il risultato:
C:\Progetti\LunaRss>ruby "lunarss v0.7.rb" Loaded suite lunarss v0.7 Started F Finished in 0.032 seconds. 1) Failure: test_this(TestLunaRss) [lunarss v0.7.rb:194]: <true> expected but was <false>. 1 tests, 1 assertions, 1 failures, 0 errors
ok, ci siamo cambio il codice per far passare il test d’esempio ed inizio con la scrittura del primo test.
ecco il test:class TestLunaRss < Test::Unit::TestCase def test_parser parser = RssParser.new("test") stubLoader = FeedLoaderStub.new parser.inject_loader! stubLoader original_data = FeedData.new( "Ruby Italia", "Chiaroscuro", "description too long", "http://ruby-it.org/pages/Chiaroscuro#936" ) parsed_data = parser.esegui_parsing assert_equal original_data, parsed_data end ended ecco lo stub del FeedLoader:
class FeedLoaderStub def get_feed url <<-HTML <?xml version="1.0"?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>Ruby Italia</title> <link>http://ruby-it.org/</link> <description>Tracking all versions for Ruby Italia</description> <language>it-it</language> <ttl>40</ttl> <item> <title>Chiaroscuro</title> <description>description too long</description> <pubDate>Mon, 08 May 2006 13:33:54 +0200</pubDate> <guid>http://ruby-it.org/pages/Chiaroscuro#936</guid> <link>http://ruby-it.org/pages/Chiaroscuro#936</link> <dc:creator>Chiaroscuro</dc:creator> </item> </channel> </rss> HTML end endma il test fallisce perchè sono un caprone in ruby :P
C:\Progetti\LunaRss>ruby "lunarss v0.7.rb" Loaded suite lunarss v0.7 Started F Finished in 0.031 seconds. 1) Failure: test_parse_simple(TestLunaRss) [lunarss v0.7.rb:229]: <#<struct FeedData channel="Ruby Italia", titles="Chiaroscuro", descriptions="description too long", links="http://ruby-it.org/pages/Chiaroscuro#936">> expected but was <#<struct FeedData channel=[["Ruby Italia"]], titles=[["Chiaroscuro"]], descriptions=[["description too long"]], links=[["http://ruby-it.org/pages/Chiaroscuro#936"]]>>. 1 tests, 1 assertions, 1 failures, 0 errorsho dovuto quindi cambiare il test in questo modo per farlo passare:
def test_parser parser = RssParser.new("test") stubLoader = FeedLoaderStub.new parser.inject_loader! stubLoader data = parser.esegui_parsing assert_equal "Ruby Italia".to_s, data.channel[0].to_s assert_equal "Chiaroscuro".to_s, data.titles[0].to_s assert_equal "description too long".to_s, data.descriptions[0].to_s assert_equal "http://ruby-it.org/pages/Chiaroscuro#936".to_s, data.links[0].to_s end
ed ecco il codice finale, ben lungi dall’essere bello, ma volevo dare uno spunto per iniziare a scrivere i test, ora mi vado a riposare un pò che son cotto, ah un’ultima cosa io avrei già iniziato a creare diversi file per evitare il paciugone ma per il wiki forse conviene continuare a tenerlo accussì:
require 'net/http'
FeedData = Struct.new :channel,
:titles,
:descriptions,
:links
class FeedLoader
def initialize(proxy=nil)
@http_proxy = proxy
end
def get_feed url
url_no_http = url.gsub(/http\:\/\//,'')
url_http = url_no_http.gsub(/\/.*/,'')
url_pagina = "/" + url.gsub(%r{http:\/\/.*?\/},'')
if @http_proxy.nil?
h = Net::HTTP.new(url_http)
else
proxy_uri = URI.parse(@http_proxy)
h = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(url_http)
end
resp,data = h.get(url_pagina,nil)
data.gsub!(/\0/,'')
return data
end
end
class RssParser
def initialize(url, proxy=nil)
@feed_loader = FeedLoader.new(proxy)
@url = url
end
def inject_loader! feed_loader
@feed_loader = feed_loader
end
def esegui_parsing
return FeedData.new(
parse( channel_title_pattern ),
parse( item_title_pattern ),
parse( item_description_pattern ),
parse( item_links_pattern )
)
end
private
def get_raw_data
@feed_loader.get_feed @url
end
def rss_data
@data ||= get_raw_data
end
def parse pattern
output_data = []
rss_data.scan pattern do |x|
output_data << x
end
return output_data
end
def channel_title_pattern
%r{<channel(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</channel>}m
end
def item_title_pattern
%r{<item(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</item>}m
end
def item_links_pattern
%r{<item(?!s).*?>.*?(?:<link>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</link>.*?)?</item>}m
end
def item_description_pattern
%r{<item(?!s).*?>.*?(?:<description>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</description>.*?)?</item>}m
end
end
##############################
def align text
text.gsub(/^\s*\./m, '')
end
##############################
class RssMaker
def header
align <<-HTML
.Content-type: text/html\r\n\r\n
.<html>
.<body>
HTML
end
def footer
align <<-HTML
.</body>
.</html>
HTML
end
def channel name
align <<-HTML
.<h3>#{name}</h3>
HTML
end
def entry titolo, descrizione, link
align <<-HTML
.<strong>
. <a href="#{link}"> #{titolo} </a>
.</strong><br/>
.
.<font size="-1"> #{descrizione} </font>
.<p/>
HTML
end
end
##############################
# Configurations
feeds=[
'http://www.repubblica.it/rss/scienza_e_tecnologia/rss2.0.xml',
'http://programmazione.it/rss.xml',
'http://www.hwupgrade.it/rss_news.xml',
'http://www.hwupgrade.it/rss_articoli.xml',
'http://www.beppegrillo.it/index.xml'
]
NEED_PROXY = false #switch this if you have a proxy
proxy_url = "http://10.0.0.2:8080" #put here your proxy, if you have one
##############################
class LunaRss
def Get_Feeds
rss_make = RssMaker.new
puts rss_make.header
feeds.each do |feed|
if NEED_PROXY
parser = RssParser.new feed, proxy_url
else
parser = RssParser.new feed
end
data = parser.esegui_parsing
puts rss_make.channel( data.channel )
0.upto data.titles.length do|i|
puts rss_make.entry(
data.titles[i],
data.descriptions[i],
data.links[i]
)
end
end
puts rss_make.footer
end
end
require 'test/unit'
class FeedLoaderStub
def get_feed url
<<-HTML
<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Ruby Italia</title>
<link>http://ruby-it.org/</link>
<description>Tracking all versions for Ruby Italia</description>
<language>it-it</language>
<ttl>40</ttl>
<item>
<title>Chiaroscuro</title>
<description>description too long</description>
<pubDate>Mon, 08 May 2006 13:33:54 +0200</pubDate>
<guid>http://ruby-it.org/pages/Chiaroscuro#936</guid>
<link>http://ruby-it.org/pages/Chiaroscuro#936</link>
<dc:creator>Chiaroscuro</dc:creator>
</item>
</channel>
</rss>
HTML
end
end
class TestLunaRss < Test::Unit::TestCase
def test_parser
parser = RssParser.new("test")
stubLoader = FeedLoaderStub.new
parser.inject_loader! stubLoader
data = parser.esegui_parsing
assert_equal "Ruby Italia".to_s, data.channel[0].to_s
assert_equal "Chiaroscuro".to_s, data.titles[0].to_s
assert_equal "description too long".to_s, data.descriptions[0].to_s
assert_equal "http://ruby-it.org/pages/Chiaroscuro#936".to_s, data.links[0].to_s
end
end