tag:blogger.com,1999:blog-52162502923818657402024-03-14T02:31:35.838-04:00Cron JobNothing to do with cronjob's, just things that I learn while doing my jobjeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.comBlogger39125tag:blogger.com,1999:blog-5216250292381865740.post-62019257515294434802012-09-14T13:15:00.001-04:002012-09-14T13:15:28.779-04:00Git Extensions 240 on Ubuntu 12.04While I do most of my git work from the command line, I occasionally use <a href="http://code.google.com/p/gitextensions/" target="_blank">GitExtensions</a> for viewing the history of commits and for it's visualization of which commits are in which branch. When converting to Ubuntu I was glad to find out that GitExtensions worked on Linux, but it was not as clear on how to set it up. Apparently, the Linux support for GitExtensions is not as good as the Windows support. GitExtensions is written in C# and utilizes mono to be able to run cross-platform.<br />
<br />
I spent some time trying to figure out how to get this to run on Ubuntu. There is a <a href="http://youtu.be/zk2MMUQuW4s" target="_blank">youtube</a> video about getting this to work in Ubuntu 11.04 but after following the steps shown, I still could not get it to work.<br />
<br />
Here is what I ended up doing. I <a href="http://code.google.com/p/gitextensions/downloads/list" target="_blank">downloaded</a> the .zip file for Windows and Linux and extracted it into <i>/home/apps.</i> From the terminal, I ran:<br />
<blockquote class="tr_bq">
$ mono /home/apps/GitExtensions/GitExtensions.exe</blockquote>
which produced the following error:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">Unhandled Exception: System.TypeLoadException: Could not load type 'GitUI.FormChooseTranslation' from assembly 'GitUI, Version=2.40.0.0, Culture=neutral, PublicKeyToken=null'.</span><span style="font-size: x-small;">[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not load type 'GitUI.FormChooseTranslation' from assembly 'GitUI, Version=2.40.0.0, Culture=neutral, PublicKeyToken=null'.</span></blockquote>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
While searching for a solution for this, I came across a <a href="https://groups.google.com/d/topic/gitextensions/EUrRGQMlj_U/discussion" target="_blank">thread</a> in the Google Group for GitExtensions that led me to downloading MonoDevelop. Apparently even though I had the Mono Runtime and the Mono Runtime (Terminal), MonoDevelop is also needed for GitExtensions to work.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-6hHqP6060WM/UFNfvBa2dpI/AAAAAAAACC0/7FdZeyQhsks/s1600/monoinstalled.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="272" src="http://2.bp.blogspot.com/-6hHqP6060WM/UFNfvBa2dpI/AAAAAAAACC0/7FdZeyQhsks/s400/monoinstalled.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Installed mono software</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: left;">
After installing MonoDevelop, GitExtensions opened with no problem at all. I was able to select my language and configure it for first time use.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
One more thing that I wanted was an icon on the launcher so I didn't need to keep running this from the terminal. <a href="http://www.ubuntugeek.com/how-to-create-desktop-launchers-in-ubuntu-11-10oneiric.html" target="_blank">This</a> post helped me out there. From the terminal run:</div>
<blockquote class="tr_bq">
$ sudo apt-get install --no-install-recommends gnome-panel</blockquote>
and then to create a launcher:<br />
<blockquote class="tr_bq">
$ gnome-desktop-item-edit ~/Desktop/ --create-new</blockquote>
The icon can be changed to the GitExtensions icon but you have to first change it to an image format such as .jpeg or .gif. Open the .ico file that came with GitExtensions in an image editing program and save it as a .jpeg or .gif. Then in the Create Launcher window, click on the icon in the top left and select the file that you just created. Give the launcher a name and for its command set it to 'mono' and then the path of GitExtensions.exe. Here is mine:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-ttTaK-h8q24/UFNkepu7xAI/AAAAAAAACDE/45Ob-SAEaGk/s1600/createlauncher.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="122" src="http://1.bp.blogspot.com/-ttTaK-h8q24/UFNkepu7xAI/AAAAAAAACDE/45Ob-SAEaGk/s400/createlauncher.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Git Extensions Launcher</td></tr>
</tbody></table>
This will place the launcher on the desktop. To move this launcher to the Launcher, just drag and drop it onto the Launcher. You will notice that it appears both in the Launcher and on the desktop. To avoid this, move the launcher from the desktop to another folder such as <i>/home, </i>and then from there, drag it to the Launcher.<br />
<br />jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com3tag:blogger.com,1999:blog-5216250292381865740.post-41168564505198874472012-09-13T11:56:00.001-04:002012-09-14T08:53:25.452-04:00Switch to Ubuntu: Remmina Remote Desktop ClientThe switch to Ubuntu 12.04 from Windows 7 has been pretty seamless so far and I find that I enjoy using it. I've found several things so far that I like using better than the Windows counterpart; for instance, <a href="http://remmina.sourceforge.net/" target="_blank">Remmina Remote Desktop Client</a> over Windows' RDP interface. Remmina came with my version of Ubuntu, but it is also not difficult to install.<br />
<br />
With Remmina, you setup a connection once with all of the parameters for that server, and every time you need to connect after that, Remmina will connect and log in with just one click.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-tS_09plWitA/UFH86154phI/AAAAAAAACCE/91-XmNKJ21E/s1600/Screenshot+from+2012-09-13+11:33:28.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="http://2.bp.blogspot.com/-tS_09plWitA/UFH86154phI/AAAAAAAACCE/91-XmNKJ21E/s400/Screenshot+from+2012-09-13+11:33:28.png" width="330" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Remmina Connection Profile</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-COGZTqcYi5A/UFH_h2vlCaI/AAAAAAAACCU/MmFxJ0c8mGU/s1600/untitled.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="291" src="http://1.bp.blogspot.com/-COGZTqcYi5A/UFH_h2vlCaI/AAAAAAAACCU/MmFxJ0c8mGU/s320/untitled.jpeg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Remmina one-click connection</td></tr>
</tbody></table>
A feature of Remmina that makes it better than the similar product in Windows is tabbing the connections when multiple connections are in use at the same time.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-qU8dfN4lbO4/UFIBu4pqRQI/AAAAAAAACCk/-Do2OuCNNtw/s1600/tabs.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="150" src="http://1.bp.blogspot.com/-qU8dfN4lbO4/UFIBu4pqRQI/AAAAAAAACCk/-Do2OuCNNtw/s400/tabs.jpeg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Remmina multiple connections</td></tr>
</tbody></table>
I'm looking forward to learning more about Ubuntu and will post more of what I learn when I get time.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-2174174198107068572012-09-11T08:49:00.000-04:002012-09-11T08:49:51.430-04:00Setting up Ubuntu for the first timeRecently we've seen a shift here at work to start using Linux OS's for as much work as we can. I've not been as quick to jump on that bandwagon but decided last Friday to use the Windows installer for Ubuntu and setup my system to dual-boot Windows 7 and Ubuntu 12.04.<br />
<br />
With a little help from Google and my co-workers, I've been able to figure out many of the things that I've wanted to use Ubuntu for but still feel like there's so much more.
The biggest trouble that I've had so far has been with docking my laptop. Initially there wasn't any problem until I activated additional drivers for my NVIDIA graphics card.
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-p-SJ5hfW7t0/UE8vmhHiZtI/AAAAAAAACB0/GZqmo3rhH-A/s1600/Screenshot%2Bfrom%2B2012-09-11%2B08%253A30%253A47.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="360" src="http://2.bp.blogspot.com/-p-SJ5hfW7t0/UE8vmhHiZtI/AAAAAAAACB0/GZqmo3rhH-A/s640/Screenshot%2Bfrom%2B2012-09-11%2B08%253A30%253A47.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Additional Drivers window - showing the NVIDIA drivers</td></tr>
</tbody></table>
<br />
Not knowing what I was doing, I activated the drivers and expected them to work just fine, but when the laptop was docked nothing would show on the monitors. I have a Dell laptop, docking station, and two 24" monitors and after activating these drivers, the monitors kept saying they were going into standby mode. For whatever reason, the laptop screen didn't have any issues - just when the laptop was docked.<br />
<br />
The resolution (no pun intended) to this was to de-activate the drivers and reboot.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-131394957030568382012-06-27T09:42:00.001-04:002012-06-27T11:21:33.493-04:00Erlang syntax highlight for Notepad++ (Obsidian style)<a href="http://notepad-plus-plus.org/">Notepad++</a> does not come out of the box with a syntax highlighter for Erlang, but it does come with the support for creating a User Defined Language. <a href="http://www.roberthorvick.com/2009/07/08/syntax-highlighing-for-erlang-in-notepad/">Here</a> is a syntax highlighter that I found to be almost what I needed. I use the Obsidian style and so I needed to make a couple of changes.
<br/><br/><a href="https://docs.google.com/open?id=0B1O12Ptke0oEcU5NbmpmSEtPUG8">Here</a> is my syntax highlighter for Erlang using the Obsidian style. Import it into Notepad++ by going to View > User Defined Dialogue and clicking on Import.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-74122634785799644022012-03-26T09:13:00.000-04:002012-03-26T09:13:39.425-04:00git: Rename the Directory Containing a RepositoryWhen we thought about doing this it seemed like it was going to be a big deal but it turned out to be pretty simple. The following steps accomplished what was necessary:<br />
<br />
1. Modify gitosis.conf to add the new directory<br />
<br />
[group foo]<br />
writable = foo<br />
members = @developers<br />
<br />
[group foo_readonly]<br />
readonly = foo<br />
members = @designers @developers<br />
<br />
[group bar]<br />
writable = bar<br />
members = @developers<br />
<br />
[group bar_readonly]<br />
readonly = bar<br />
members = @designers @developers<br />
<br />
2. mv oldDir newDir<br />
<br />
On origin, run the bash 'mv' command<br />
mv foo bar<br />
<br />
3. Work with new code<br />
<br />
On my development machine, run git clone on the new directory and start working with the files. In our case we were using the old directory name for a new project. Running git pull from my development machine created an empty git repository on origin with the old directory name.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-62114364865124960422012-03-20T22:03:00.000-04:002012-03-20T22:03:27.544-04:00Matcher maker Matcher maker .... make me a MatcherRan into a problem at work today that we as a pair were close to giving up on before we finally came across the solution. We had an existing test that was ensuring that our mocked method was called with a pointer argument.<br />
<br />
Here is that test:<br />
<pre class="cpp" name="code">using ::testing::Return;
TEST(MessageDataTests, SendResponseIsCalledWithMap)
{
CString messageId = "TestMessageId";
TXMLDataMap* xmlDataMap = new TXMLDataMap();
(*xmlDataMap)["MsgId"] = messageId;
MockTranslator *translator = new MockTranslator();
EXPECT_CALL(*translator, SendResponse(xmlDataMap))
.WillOnce(Return());
translator->GetMessageData(xmlDataMap);
}
</pre><br />
As you can see, this test is just ensuring that when <i>SendResponse </i>is called, it is called with the pointer <i>xmlDataMap</i>. We needed to add an expectation on part of what <i>xmlDataMap </i>was pointing too. Google Mock can accomplish this with <i>Pointee</i>(m) where m is a <i>Matcher</i>. Our pointer is not a simple type so we had to create our own matcher to check to see if our map contained the item we were adding inside of <i>GetMessageData</i>.<br />
<br />
Here is what the final code looked like:<br />
<pre class="cpp" name="code">using ::testing::Return;
using ::testing::Pointee;
using ::testing::AllOf;
MATCHER_P(MapContainsValue, valueToCheck, "")
{
return (arg.find(valueToCheck) != arg.end());
}
TEST(MessageDataTests, MapContainsDataWhenSendResponseIsCalled)
{
CString messageId = "TestMessageId";
TXMLDataMap* xmlDataMap = new TXMLDataMap();
(*xmlDataMap)["MsgId"] = messageId;
MockTranslator *translator = new MockTranslator();
EXPECT_CALL(*translator, SendResponse(
Pointee(AllOf(MapContainsValue("MsgId"),
MapContainsValue("Data")))))
.WillOnce(Return());
translator->GetMessageData(xmlDataMap);
}
</pre>jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-14224952617389410752011-10-07T15:55:00.000-04:002011-10-07T15:55:45.236-04:00Auto-deploy feature fileFeature file for our auto-deploy: <br />
<br />
@Install<br />
Scenario: Install and Configure Virtual Hold on a remote machine<br />
Given I stop the Virtual Hold services<br />
And I uninstall if already installed<br />
And I install the media on a remote machine<br />
And I configure the media on a remote machine<br />
And I can log into EyeQueue<br />
And I start the Virtual Hold services<br />
Then Virtual Hold is running properly<br />
<br />
When the file references Virtual Hold it is talking about the collection of windows and web services that are needed to make our software work. EyeQueue is the web application that is used to make configuration changes for the Virtual Hold software.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-899468959199157912011-09-26T08:39:00.000-04:002011-09-26T08:39:36.313-04:00Automation: Auto-deployOne of the biggest time savers that has been implemented recently at our company has been something that we call an auto-deploy. Our software consists of windows services, web services, web applications, and databases; installing and configuring a system to test against can take quite a while when doing the entire process manually. A handful of individuals here have been working to improve this process by creating an auto-deploy process that will automate the following:<br />
<ul><li>Uninstall the software if previously installed</li>
<li>Copy the latest build of the software to the server</li>
<li>Install the software</li>
<li>Configure the databases</li>
<li>Start the software</li>
<li>Check the software status to ensure that it is running</li>
</ul>This used to take easily 30 minutes and sometimes several hours. The problems before mostly revolved around finding the right configuration for the server and setting up the configuration in the database through a combination of wizard screens in our windows app and different pages of our web application. (Just to explain a little about the configuration, our software is capable of talking to multiple types of telephone switches and only certain servers in our lab are configured to talk to certain switches in the lab. Because not any server can talk to any switch, the difficulty was figuring out where the configuration for Server A's connection to Switch B is and then deciphering the excel document that the lab tech's use to keep track of the configured numbers on the switch.)<br />
<br />
Now, within ten minutes I can have a system installed with the latest version and fully configured for testing. It takes about 20 minutes to setup an auto-deploy for a server for the first time, and usually within the first two or three times it is run, all of the kinks have been worked out for that environment.<br />
<br />
<br />
The configuration for the server is now contained within a .yml file that is read in by ruby code which is called from a scenario in a cucumber feature file. A Jenkins job is setup for each server configuration, and this job runs the installation feature. Because it is in Jenkins, it is available to put on our reader board that shows each of our projects' build status.<br />
<br />
Our team has already seen the benefit of this. There was a bug introduced in the code that caused the services not to start. Because we have this as part of our CI, we were able to know that a problem was introduced within an hour. Without CI and the auto-deploy, this could have taken days until another build was completed.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0123 Heritage Woods Dr, Akron, OH 44321, USA41.1324725 -81.65993409999998741.132470999999995 -81.659943099999992 41.132474 -81.659925099999981tag:blogger.com,1999:blog-5216250292381865740.post-5530456722408264692011-08-26T13:50:00.000-04:002011-08-26T13:50:18.113-04:00Making Daily Standups .... Interesting: Days 12-15I got a little behind in posting these. The contest is now over, but for your viewing pleasure:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-rkqhcgv7dJc/TlfcmpKSZZI/AAAAAAAACAs/RiAs0h0kJ70/s1600/darth_vader.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://1.bp.blogspot.com/-rkqhcgv7dJc/TlfcmpKSZZI/AAAAAAAACAs/RiAs0h0kJ70/s320/darth_vader.jpg" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Darth Vader</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-X2_6u_VXnGs/Tlfcm8EAuFI/AAAAAAAACAw/hHz1JourJSs/s1600/green_cowgirl.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="239" src="http://3.bp.blogspot.com/-X2_6u_VXnGs/Tlfcm8EAuFI/AAAAAAAACAw/hHz1JourJSs/s320/green_cowgirl.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Green Cowgirl (with lights)</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-T3Nf7fjgScc/TlfcnXIUIuI/AAAAAAAACA0/1zWl1FOmY9E/s1600/tiara.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://2.bp.blogspot.com/-T3Nf7fjgScc/TlfcnXIUIuI/AAAAAAAACA0/1zWl1FOmY9E/s320/tiara.jpg" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tiara</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-BJ2no7htHlI/TlfcpWhXcKI/AAAAAAAACA4/9H0XhjXkGiY/s1600/pink+cowgirl.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://3.bp.blogspot.com/-BJ2no7htHlI/TlfcpWhXcKI/AAAAAAAACA4/9H0XhjXkGiY/s320/pink+cowgirl.jpg" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Pink Cowgirl (with lights)</td></tr>
</tbody></table><br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com3tag:blogger.com,1999:blog-5216250292381865740.post-51361166641602823562011-08-19T09:51:00.000-04:002011-08-19T09:51:03.486-04:00Making Daily Standups .... Interesting: Day 11Here's a viking quote to go along with today's hat: <br />
<blockquote><div style="font-family: inherit;"><span style="font-size: small;"><span style="color: black;">Never walk away from home ahead of your axe and sword. You can't feel a battle in your bones or foresee a fight. </span></span><span style="font-size: small;"><span style="color: black;"><br />
</span></span></div><div style="text-align: right;"><span style="font-size: small;"><span style="color: black;"> - The Havamal </span></span></div></blockquote><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-1U4Yj0vgkYM/Tk5qJQsG9qI/AAAAAAAACAk/0mvrHZ3P8ZE/s1600/0819110932.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://4.bp.blogspot.com/-1U4Yj0vgkYM/Tk5qJQsG9qI/AAAAAAAACAk/0mvrHZ3P8ZE/s640/0819110932.jpg" width="640" /></a></div><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-4B7lRUzRn3o/Tk5qJwyK58I/AAAAAAAACAo/KdAc6kwkz_g/s1600/0819110932a.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://4.bp.blogspot.com/-4B7lRUzRn3o/Tk5qJwyK58I/AAAAAAAACAo/KdAc6kwkz_g/s640/0819110932a.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Viking helmet</td></tr>
</tbody></table><br />
<br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-29888960162154302542011-08-18T09:46:00.000-04:002011-08-18T09:46:31.675-04:00Making Daily Standups .... Interesting: Day 10Maiwaige. Maiwaige is what bwings us togewer today.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-45KCLFiuEAA/Tk0XYUv3eQI/AAAAAAAACAY/hQ5cs4ikPYI/s1600/0818110932.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://1.bp.blogspot.com/-45KCLFiuEAA/Tk0XYUv3eQI/AAAAAAAACAY/hQ5cs4ikPYI/s640/0818110932.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Some help with the veil</td></tr>
</tbody></table> <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-4e-tiXHquGk/Tk0XZmtYo8I/AAAAAAAACAg/6IDuQsx7TTI/s1600/0818110932b.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://2.bp.blogspot.com/-4e-tiXHquGk/Tk0XZmtYo8I/AAAAAAAACAg/6IDuQsx7TTI/s640/0818110932b.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Mickey (Minnie?) Mouse wedding veil</td></tr>
</tbody></table><br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com3tag:blogger.com,1999:blog-5216250292381865740.post-52258635910702189072011-08-17T09:42:00.000-04:002011-08-17T09:42:18.689-04:00Making Daily Standups .... Interesting: Day 9Not really sure what kind of hat this is, but definitely another good entry.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-Ilq9nbpvo94/TkvEzu2u29I/AAAAAAAACAU/x1oIo8Q10Ew/s1600/0817110929.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://2.bp.blogspot.com/-Ilq9nbpvo94/TkvEzu2u29I/AAAAAAAACAU/x1oIo8Q10Ew/s640/0817110929.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Fuzzy Purple 'Lamp Shade'</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-HZrPzhu1Q_0/TkvEyI4cZrI/AAAAAAAACAQ/wP2jUE7qKkA/s1600/0817110928.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://4.bp.blogspot.com/-HZrPzhu1Q_0/TkvEyI4cZrI/AAAAAAAACAQ/wP2jUE7qKkA/s640/0817110928.jpg" width="640" /></a></div><br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-81802874190496978362011-08-16T12:30:00.000-04:002011-08-16T12:30:33.481-04:00Making Daily Standups .... Interesting: Day 8We had retrospective yesterday so no standup. If you look at the wall, you can get a sneak peek at a couple of the hats coming up.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-e-nM_g9iQkg/Tkqa5pbSWoI/AAAAAAAACAM/L_yhaSiNQa8/s1600/0816110931.jpg" imageanchor="1"><img border="0" height="480" src="http://1.bp.blogspot.com/-e-nM_g9iQkg/Tkqa5pbSWoI/AAAAAAAACAM/L_yhaSiNQa8/s640/0816110931.jpg" width="640" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-82519677559805202732011-08-12T09:49:00.000-04:002011-08-12T09:49:58.728-04:00Making Daily Standups .... Interesting: Day 7It looks like someone was getting desperate for a hat entry.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-dvoN-CmbFL0/TkUvGpU5-JI/AAAAAAAACAI/Lm0MTn1TPbs/s1600/0812110932.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://4.bp.blogspot.com/-dvoN-CmbFL0/TkUvGpU5-JI/AAAAAAAACAI/Lm0MTn1TPbs/s640/0812110932.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Potted plant</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"></div>No - he didn't wear this on his head for the entire standup.<br />
<br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-45789662422952135462011-08-11T09:53:00.000-04:002011-08-11T09:53:15.953-04:00Making Daily Standups .... Interesting: Day 6A Viking hat with Germany's national colors is today's entry into the standup hat contest. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-wWZUQkZEClM/TkPdjXbf2JI/AAAAAAAACAA/FvqfrWf7wJk/s1600/0811110930.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://2.bp.blogspot.com/-wWZUQkZEClM/TkPdjXbf2JI/AAAAAAAACAA/FvqfrWf7wJk/s640/0811110930.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Viking</td></tr>
</tbody></table>It is kinda hard to take him seriously with these ridiculous looking hats, but it does make it more interesting.<br />
<br />
Standups have become better recently, but I still think that there could be more improvement that would make standup meaningful for those involved. <br />
<br />
<br />
<br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com2tag:blogger.com,1999:blog-5216250292381865740.post-34573770137471644292011-08-10T10:55:00.000-04:002011-08-10T10:55:56.692-04:00Making Daily Standups .... Interesting: Day 5Our illustrious scrum master was out yesterday but returned today to sport this hat<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-_8vZJ82cn-4/TkKbxATWZVI/AAAAAAAAB_8/3cAmH70Iq54/s1600/0810110940.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="640" src="http://2.bp.blogspot.com/-_8vZJ82cn-4/TkKbxATWZVI/AAAAAAAAB_8/3cAmH70Iq54/s640/0810110940.jpg" width="480" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Jesters Hat, with bells</td></tr>
</tbody></table><br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-72877241404536366522011-08-08T12:22:00.000-04:002011-08-08T12:22:02.261-04:00Making Daily Standups .... Interesting: Day 4Today's hat was not a bad look for him. I could see him wearing this away from work.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-Am_ZJr6JUT8/Tj_2w0apL9I/AAAAAAAAB_4/yKIDIRrqnsk/s1600/0808110936.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://3.bp.blogspot.com/-Am_ZJr6JUT8/Tj_2w0apL9I/AAAAAAAAB_4/yKIDIRrqnsk/s640/0808110936.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Propeller Hat</td></tr>
</tbody></table><br />
<br />
<br />
<br />
jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-86912934449701003552011-08-05T10:01:00.000-04:002011-08-05T10:01:41.266-04:00Making Daily Standups .... Interesting: Day 3Another good entry in the hat contest:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-bKgjDnXmViU/Tjv29CokWRI/AAAAAAAAB_0/zYtAqs38yKA/s1600/0805110937.jpg" imageanchor="1"><img border="0" height="480" src="http://2.bp.blogspot.com/-bKgjDnXmViU/Tjv29CokWRI/AAAAAAAAB_0/zYtAqs38yKA/s640/0805110937.jpg" width="640" /></a></div><br />
<br />
This is something I could see him wearing away form work.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-12956193329581963312011-08-04T10:08:00.000-04:002011-08-04T10:08:23.263-04:00Making Daily Standups .... Interesting: Day 2Day 2 of the hat contest sees a milder, less 'anxious' headgear piece.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-qbprzMAbMVM/Tjqm_WNv7SI/AAAAAAAAB_s/TKA3W6_YmW0/s1600/0804110931.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://4.bp.blogspot.com/-qbprzMAbMVM/Tjqm_WNv7SI/AAAAAAAAB_s/TKA3W6_YmW0/s640/0804110931.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"> Rajastan hat (Indian)</td></tr>
</tbody></table>Apparently, this is some form of tribal headgear from the Indian state of <a href="http://en.wikipedia.org/wiki/Rajasthan">Rajasthan</a>.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-40678718691677160072011-08-04T08:54:00.000-04:002011-08-05T08:04:18.719-04:00Making Daily Standups .... Interesting: Day 1UPDATE: added additional photo<br />
<br />
Our new Scrum Master has promised to wear any headgear that we bring in for the daily standup. Here is the first hat that he had to wear:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-qCJKdXe6Cj4/TjlQ7DT7RSI/AAAAAAAAB_o/ysPzXq_XbwY/s1600/0803110937.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="480" src="http://3.bp.blogspot.com/-qCJKdXe6Cj4/TjlQ7DT7RSI/AAAAAAAAB_o/ysPzXq_XbwY/s640/0803110937.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Raggedy Ann - complete with bangs and pigtails</td></tr>
</tbody></table><br />
He has promised to do this for a couple of weeks, two sprints I believe, and the reward is a gift certificate for a local restaurant. It should be interesting as the weeks go on to see what members of the team can come up with for him to wear.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-y06utFhEpnM/Tjvb80Rg5iI/AAAAAAAAB_w/C8dkvWaR2Co/s1600/john-raggedyann.jpg" imageanchor="1"><img border="0" height="480" src="http://3.bp.blogspot.com/-y06utFhEpnM/Tjvb80Rg5iI/AAAAAAAAB_w/C8dkvWaR2Co/s640/john-raggedyann.jpg" width="640" /></a></div><br />
<br />
<span id="goog_986481717"></span><span id="goog_986481718"></span>jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com2tag:blogger.com,1999:blog-5216250292381865740.post-27193267031687345262011-07-14T09:00:00.000-04:002011-07-14T09:00:23.778-04:00Python VideosYouTube links for a Python class given at Google by <a href="http://www-cs-faculty.stanford.edu/%7Enick/">Nick Parlante</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/tKTZoB2Vjuk?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"><i>Day 1 Part 1</i></div><div style="text-align: left;"></div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/EPYupizJYQI?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"> <i>Day 1 Part 2</i></div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/haycL41dAhg?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"><i>Day 1 Part 3</i></div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/kWyoYtvJpe4?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"><i>Day 2 Part 1</i></div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/uKZ8GBKmeDM?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"><i>Day 2 Part 2</i></div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Nn2KQmVF5Og?feature=player_embedded' frameborder='0'></iframe></div><div style="text-align: center;"><i>Day 2 Part 3</i></div><div class="separator" style="clear: both; text-align: center;"><br />
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/IcteAbMC1Ok?feature=player_embedded' frameborder='0'></iframe></div><br />
<div style="text-align: center;"> <i>Day 2 Part 4</i></div>jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-44836827353591162882011-06-29T09:31:00.000-04:002011-06-29T10:43:36.112-04:00Learning Python: #5 - Finish Bowling Game KataMy finished test class TestGame.py:<br />
<pre class="python" name="code">import unittest
import Game
class TestGame(unittest.TestCase):
def setUp(self):
self.game = Game.Game()
def testGutterGameHasZeroScore(self):
for i in range(20):
self.game.roll(0)
assert self.game.score() == 0, "Score is zero"
def testGameAllOnesHasScoreOfTwenty(self):
for i in range(20):
self.game.roll(1)
assert self.game.score() == 20
def testGameThrowsExceptionWithMoreThanTwentyOneRolls(self):
try:
for i in range(22):
self.game.roll(10)
except ValueError:
pass
else:
self.fail("Expected a ValueError")
def testGameWithOneSpare(self):
self.game.roll(1)
self.game.roll(9)
self.game.roll(5)
for i in range(17):
self.game.roll(0)
assert self.game.score() == 20
def testGameWithOneStrike(self):
self.game.roll(10)
self.game.roll(1)
self.game.roll(1)
for i in range(17):
self.game.roll(0)
assert self.game.score() == 14
def testPerfectGameScores300(self):
for i in range(12):
self.game.roll(10)
assert self.game.score() == 300, "Perfect Game should score 300"
if __name__ == "__main__":
unittest.main()
</pre><br />
My finished Game.py:<br />
<pre class="python" name="code">MAX_ROLLS = 21
FRAMES = 10
STRIKE = 10
SPARE = 10
class Game:
def __init__(self):
self.scoreArr = []
def roll(self, pins):
if self.numberOfRollsTaken() > MAX_ROLLS:
raise ValueError
self.scoreArr.append(pins)
def score(self):
score = 0
currentRoll = 0
frame = 0
while frame < FRAMES:
if self.scoreArr[currentRoll] == STRIKE:
score += self.scoreNextTwoBalls(currentRoll)
currentRoll += 1
elif self.frameScore(currentRoll) == SPARE:
score += self.scoreNextTwoBalls(currentRoll)
currentRoll += 2
else:
score += self.frameScore(currentRoll)
currentRoll += 2
frame = frame + 1
return score
def numberOfRollsTaken(self):
return len(self.scoreArr) +1
def scoreNextTwoBalls(self, index):
return self.scoreArr[index] + self.scoreArr[index + 1] + self.scoreArr[index + 2]
def frameScore(self, index):
return self.scoreArr[index] + self.scoreArr[index + 1]
</pre>
A couple of things that I learned while doing this Bowling Game kata:
<ul><li>It appears that it is a requirement for test methods to start with the word 'test' or PyUnit will not recognize them as tests that need to be run.</li>
<li>A variable and a method in the same class cannot both have the same name, or at least my syntax was wrong</li>
<li>The ':' at the end of class/method definitions and control statements gets me almost everytime; I cannot seem to remember that it needs to be there</li>
</ul>jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-632213302883104952011-06-28T15:28:00.000-04:002011-06-28T15:40:18.550-04:00Learning Python: #4 - UnitTesting - Second TestNow that I have the <a href="http://jeremykentc.blogspot.com/2011/06/learning-python-3-unittesting-first.html">first test</a> completed, I can move on to adding some actual functionality to the Game class. My next step was to have it keep track of the number of pins rolled. Here is my second test:<br />
<pre class="python" name="code">def testGameHasScoreOfOneWithFirstRollOfOnePin(self):
game = Game()
game.roll(1)
assert game.score == 1
</pre>At this point the tests no longer pass because the Game class does not have a roll method. My first attempt to add the roll method to my Game class failed:<br />
<pre class="python" name="code">def roll(pins):
score += pins
</pre>Here is the error that was printed:<br />
<br />
E.<br />
======================================================================<br />
ERROR: testGameHasScoreOfOneWithFirstRollOfOnePin (__main__.TestGame)<br />
----------------------------------------------------------------------<br />
Traceback (most recent call last):<br />
File "TestGame.py", line 13, in testGameHasScoreOfOneWithFirstRollOfOnePin<br />
game.roll(1)<br />
TypeError: roll() takes exactly 1 positional argument (2 given)<br />
<br />
----------------------------------------------------------------------<br />
Ran 2 tests in 0.002s<br />
<br />
FAILED (errors=1)<br />
<br />
This is a very confusing error when you are unfamiliar with the language. Clearly I am passing in one argument to a method that takes one argument. What in the world?? The way that methods work in Python is that the object is passed as the first argument of the function. So essentially, the method call acts like <i>game.roll(game, 1)</i> though it is not actually called this way. What is needed is to change the method definition. My updated roll method:<br />
<pre class="python" name="code">def roll(self, pins):
self.score += pins
</pre>Both of my tests now pass:<br />
..<br />
----------------------------------------------------------------------<br />
Ran 2 tests in 0.002s<br />
<br />
OKjeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-62045591932043786312011-06-28T14:52:00.000-04:002011-06-28T14:52:22.607-04:00Learning Python: #3 - UnitTesting - First TestI was struggling with something to write to help me learn Python and I decided to do the classic bowling game example. I did a quick search to find out how to write TDD with Python and came across <a href="http://powertwenty.com/kpd/downloads/TestDrivenDevelopmentInPython.pdf">this</a> PowerPoint slide which helped me get started writing the tests.<br />
<br />
From that ppt slide, I figured out what my test file and first test should look like.<br />
<br />
TestGame.py:<br />
<pre class="python" name="code">import unittest
class TestGame(unittest.TestCase):
pass
if __name__ == "__main__":
unittest.main()</pre>and my First Test:<br />
<pre class="python" name="code">import unittest
class TestGame(unittest.TestCase):
def testGameHasZeroScore(self):
game = Game()
assert game.score == 0, "Score is zero"
if __name__ == "__main__":
unittest.main()
</pre>At this point I am still not certain what all of this is doing. Running the test produces this output:<br />
<br />
E<br />
======================================================================<br />
ERROR: testGameHasZeroScore (__main__.TestGame)<br />
----------------------------------------------------------------------<br />
Traceback (most recent call last):<br />
File "TestGame.py", line 7, in testGameHasZeroScore<br />
game = Game()<br />
NameError: global name 'Game' is not defined<br />
<br />
----------------------------------------------------------------------<br />
Ran 1 test in 0.002s<br />
<br />
FAILED (errors=1)<br />
<br />
This is good then because I know that I'm using the unittest import correctly. At this point I wasn't familiar with why<i> self </i>was<i> </i>being passed to the test method but I assumed it had a need. I found out later why it was needed. To get this test to pass I had to create a Game.py file that created my Game class with a score member, and I had to add<i> from Game import Game</i> to my TestGame.py file under the current import statement. Here is my Game class:<br />
<br />
Game.py:<br />
<pre class="python" name="code">class Game:
score = 0
</pre><br />
And my TestGame.py:<br />
<pre class="python" name="code">import unittest
from Game import Game
class TestGame(unittest.TestCase):
def testGameHasZeroScore(self):
game = Game()
assert game.score == 0, "Score is zero"
if __name__ == "__main__":
unittest.main()
</pre><br />
Running this now produces this output:<br />
<br />
.<br />
----------------------------------------------------------------------<br />
Ran 1 test in 0.001s<br />
<br />
OK<br />
<br />
Awesome! I have completed my first unit test with Python.jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0tag:blogger.com,1999:blog-5216250292381865740.post-26644194988982712852011-06-27T14:43:00.000-04:002011-06-27T14:43:47.451-04:00Learning Python: #2 - Five Interesting ThingsSo, I'm going through the <a href="http://docs.python.org/py3k/tutorial/index.html">tutorial</a> and have already found some things that I find interesting.<br />
<ol><li>Division Operators</li>
<ul><li>3/2 = 1.5</li>
</ul><ul><li>3//2 = 1 - division that produces an integer by discarding the remainder</li>
</ul><li>The _ variable will have the last thing printed in the window assigned to it</li>
<li>A \ at the end of a line will let the string literal span multiple lines</li>
<li>Indexing of strings </li>
<ul><li>"someString"[2:7] prints 'meStr'</li>
<li>"someString"[:3] prints 'som'</li>
<li>"someString"[-3:] prints 'ing'</li>
<li>"someString"[:-3] prints 'someStr'</li>
</ul><li>The built in function len() applies to both strings and lists</li>
</ol>Bonus:<br />
<ul><li>By default the print() function will end with a newline. You can specify a different ending with the keyword end</li>
<ul><li>Syntax: print(someVariable, end="|")</li>
<li>The above used in a loop will create a pipe delimited list</li>
</ul></ul>jeremykentchttp://www.blogger.com/profile/12767481590144292023noreply@blogger.com0