Hello, if you have any need, please feel free to consult us, this is my wechat: wx91due
ICS 33 Spring 2024
Project 0: History of Modern
Due date and time: Wednesday, April 10, 11:59pm
Git repository: https://ics.uci.edu/~thornton/ics33/ProjectGuide/Project0/Project0.git
Introduction
Given your successful completion of prerequisite coursework, you will have built your programming skills to the point where you can do a lot more than you could do when you wrote your first program.
- You can now solve medium-sized problems whose solutions require multiple modules consisting of multiple functions or classes, and have begun to develop sensibilities about their design: where to separate complex functionality into smaller pieces, which functions or classes should be arranged in which modules, and so on.
- You can make use of libraries that allow you to address commonly occurring parts of a problem without having to solve them from first principles. To do so, you're able to read documentation in areas with which you have only mild familiarity, so you can find the information you need even if not every detail is understandable yet.
- You have some insight about how you might test a program to ensure that it meets its requirements, and an understanding of the myriad ways that a program can be incorrect. Additionally, you've built skills that allow you to automate at least some of that testing by writing unit tests, even if you've only done so sparingly.
As you continue to climb the skills ladder in this course and beyond, you'll find yourself solving problems that are gradually larger, gradually more complex, require gradually larger teams of people to solve (and a gradually higher percentage of time spent coordinating with those people), and present gradually more ways to make mistakes both large and small. Scale introduces constraints, which means that we need tools that are designed to work within those constraints. This quarter, we'll begin an exploration of those tools, so you can hit the ground running when you reach the point where you need them. And, fortunately, those tools benefit us even we use them in individual, smaller-scale work like you'll be doing in this course.
But, of course, we can't use new tools without having learned about them, and there's no better way to learn about tools than to put them to use. This project will ask you to exercise your existing Python programming skills, but will also require you to use tools and organizational techniques that may be new for you. Your score on this project will largely be determined by your demonstration of how you used those tools and techniques throughout, so this isn't just a matter of doing whatever you prefer and submitting a complete solution; the focus is as much on how you get there as it is on whether you get there.
Setting up your development environment
It is very common in real-world software development jobs to be given, at the outset of a new job, a list of tools that you will be required to use, along with a list of policies and procedures you'll be required to follow. Flexibility is great, and it's nice to be able to choose one's own tools, but, unfortunately, many software tools introduce constraints on how a program can be written, how its components can be arranged, what functions can be called, what documentation can be written and how, what additional software it can be combined with, how it can be "built" to be distributed to end users, and so on. So, like it or not, real-world software development usually requires at least some of the tools to be set in stone and used by all members of a team, even if not all members have the same preferences; this is simply a reality that software developers have to face, because smooth collaboration in a team environment is usually more important than satisfying every individual's whim. (While your work in this course is individual, you'll nonetheless be working with a team of course staff, who won't be able to support everyone's individual tools and bespoke preferences.)
Your first task in this project, then, is to set up the development environment that we'll all be using for our work this quarter.
Developing and testing a Python module incrementally
This project isn't just about setting up tools, though. We'll also be asking you to put those tools to use to enrich your prior skills, by developing and testing a Python module in an incremental fashion. Importantly, you'll also have to demonstrate that you followed that incremental approach by submitting every version of your module as you developed and tested it, step by step. We don't just want to see where you ended up; we want to see how you got there, even if there were missteps along the way.
Don't worry, though; you'll be using the same tools that professional software developers use to achieve these same goals, so you won't need to be making copies of files and arranging your own history as you go. As long as you can take notice that you've reached stable ground periodically, and definitively plant a stake in that stable ground each time with a brief explanation of what's changed and why, the rest of the paper trail will be built for you automatically in a form that will be easily submitted to us within a single file.
A word of warning
Before you start writing any code for this project, you're going to want to read this write-up in its entirety, because how you approach this problem is at least as important as whether you can solve it. The learning objective of this project is to familiarize yourself with the tools and processes you'll be using to begin an assignment, document and test your work incrementally as you proceed with it, and submit it to us in a way that we can accept and grade using automation to assist us. That way, we can continue to rely on your ability to adhere to a similar process throughout the quarter, so that we can focus our grading efforts on providing useful feedback, rather than the secretarial work of rearranging each student's customized submission into something we can work with.
Consequently, correct solutions that do not demonstrate the use of the necessary tools and processes will receive little or no credit. Grades are an attempt to measure learning, and it's those tools and processes that you're meant to be learning in this project.
The ICS 33 development environment
This course is built around the assumption that everyone — students and course staff alike — will be using the same development environment, which is to say that we'll all be using the same versions of the same tools to do our work. That way, everyone is on an equal footing, meaning that when there's a problem, we can rule out root causes like "My version of Python doesn't have that function in its standard library" or "My preferred editor is not compatible with your preferred version control system," so we can keep our minds focused on the course material rather than fighting uphill battles against our tools.
So, your first order of business is setting up the tools you'll need for your work this quarter. There are three things you'll need to be sure you've installed.
- Python 3.12
- Git
- PyCharm Professional
Before you start downloading and installing these tools on your own, though, it's worth reading to the end of this section and reading (and following) the instructions provided for your operating system.
Choosing the right versions of tools
The version of Python is important to get right. We all need to be on version 3.12 for this course, though it's not important which minor release (e.g., 3.12.1 or 3.12.0) you install. Using any version other than 3.12 exposes you to risks that will interfere with your work and your ability to obtain a high score when we grade it — and note that you bear all of this risk.
- If you use Python 3.11 or older, there's a genuine risk that some of the code we provide won't run properly, as we'll feel free to teach and use features added in Python 3.12, and won't generally take the time to point out which features those are or how those same goals could be achieved using features from previous versions of Python.
- If you use pre-releases of Python 3.13, there's a genuine risk that you'll submit code that we won't be able to run when we grade it, because you unknowingly relied on a feature that was added in Python 3.13. We'll be grading using Python 3.12 and will not be willing to work around these issues after submission.
For both Git and PyCharm Professional, your best bet is to begin this quarter by installing (or upgrading to) whatever version is the most current at that point, and then stick with it throughout the quarter. Our work in this course is less sensitive to the particulars of these tools, though it would still be worth starting out as up-to-date as you can, then leaving things alone until after the quarter ends. The rest of these instructions assume that you've installed the versions of these tools that were available as of this writing.
The particulars of getting set up
If you'll be doing your work solely using the workstations in the ICS labs, you're ready to go! The software you need is already installed and configured properly, so there's nothing you'll need to do for this part of the project. Note, though, that some of our ICS labs are "laptop-only" spaces, so there may not always be a workstation available to you that has the necessary tools installed on it.
So, assuming that you will be wanting to do at least some of your work on your own machine, what you do next depends on what operating system you're running on your machine.
- Installing and Configuring the ICS 33 Development Environment on Windows
- Installing and Configuring the ICS 33 Development Environment on macOS
- (I expect that you'll be able to successfully use Linux in this course, since all of the necessary tools exist for Linux, as well, but the number of different distributions and competing mechanisms for installing, managing, and configuring software makes it impossible for me to provide a single set of comprehensive instructions, so you'll sadly be on your own. If you're a Linux user, however, you're probably accustomed to that!)
Getting started on your project
Each assignment will begin with a starting point, which will include a combination of provided Python code, with any other necessary tools to use for setup and submission. The starting point is provided in the form of a Git repository. (We'll discuss Git in some more detail a little later in this write-up.)
Using PyCharm on the workstations in the ICS labs
If you're using the version of PyCharm installed on the workstations in the ICS labs, you may find that you need to activate it, by connecting it to a license server that verifies that it's permitted to be used on those workstations.
If you're asked to activate PyCharm on a workstation in the ICS labs — if a dialog box named Licenses pops up — here's what you need to do.
- Click the radio button labeled Activate PyCharm.
- Underneath Get license from:, click the radio button labeled License server.
- In the box labeled Server address:, enter http://masterhit.ics.uci.edu:8181.
- Click the Activate button.
That should be it.
One-time PyCharm setup
PyCharm is a professional-level tool, which means that it has a wealth of settings that can be used to configure it. This is great when you're an experienced software developer, because it means you can set it up in a way that best supports the kind of work you'll be doing. However, when you're relatively new — as most of you are — it can be an overwhelming set of choices, many of which you won't have the context to understand yet. Even for teams of experienced developers, synchronizing on various settings — so that everyone has things configured similarly — can be an important way to keep people on the same page.
We'll all use some of the same PyCharm settings in this course, so that we'll all see warnings and errors in the same situations, we'll all use the same source control tools in the same way, and so on. Rather than require each of you to click through hundreds of settings, you're instead being provided with a collection of settings that you can simply import into PyCharm. Let's do that now.
- Download a .zip file containing the PyCharm settings at the following link. Make a note of where you've saved that file, so you'll be able to find it in the next step.
- Start up PyCharm, if it isn't running already.
-
Close any project that's already open in PyCharm (if any), so that you'll see the Welcome to PyCharm window.
- In that window, click Customize along the left-hand side.
- Next, click the link titled Import Settings....
- A dialog box titled will pop up, asking you to find the .zip file you downloaded in the previous step. Go find it and click OK.
- Another dialog box titled Select Components to Import will pop up. Click the button titled Select All, so that all of the components are selected, then click OK.
- A third dialog box, titled Restart to Import Settings, will pop up. Click the button titled Import and Restart, which will restart PyCharm, after which the settings will have been updated.
Additionally, you'll want to disable any generative AI plugins that PyCharm will have installed, both because we are not permitting the use of generative AI in this course — see the Course Reference for details — and because we've found that the suggestions offered have been vastly more confusing than they've been useful. (It's worth noting that PyCharm offers these plugins mainly as a way to obtain subscription revenue.) Here's how to disable the AI-related plugins.
- Start up PyCharm, if it isn't running already.
-
Close any project that's already open in PyCharm (if any), so that you'll see the Welcome to PyCharm window.
- In that window, click Plugins along the left-hand side.
- If it's not selected already, click the word Installed along the top of the window, so that you're seeing a list of the plugins you have currently installed.
-
You may have at least four plugins that are marked as AI-Powered, all of which you'll need to disable. On my installation, these are the four. (Yours may differ, as these things change over time.)
- AI Assistant
- Full Line Code Completion
- Machine Learning Code Completion
- Machine Learning in Search Everywhere
You'll only need to do these things once, so now's a good time to do it. Then, you can proceed with starting this project.
Starting a new project
To start a new assignment, then, you'll need to follow a few procedural steps to create a new PyCharm project using the contents of the provided Git repository.
- Start up PyCharm, if it isn't running already.
-
Close any project that's already open in PyCharm (if any), so that you'll see the Welcome to PyCharm window.
- In that window, click Projects along the left-hand side.
- Next, click the Get from VCS button near the top-right corner. (A VCS is a version control system, which is the kind of software system that Git is.)
-
A dialog box titled Get from Version Control will pop up.
- Select Repository URL along the left-hand side of that dialog box.
- Where you have a choice of Version control, select Git if it isn't selected already.
-
In the box marked URL, paste the link to the provided Git repository for the project, which you'll find listed at the top of each assignment. (There's no need to download it manually in a browser; PyCharm will download it for you.)
- For Project 0, the Git repository link is: https://ics.uci.edu/~thornton/ics33/ProjectGuide/Project0/Project0.git
- In the box marked Directory, choose the directory where you want your project work to be stored locally. For each separate assignment, you'll need a separate project directory, though you might want them all to be stored within the same parent directory (i.e., one directory for ICS 33, within which there's one for each assignment).
- Click the Clone button near the bottom-right.
- You may be asked if you want to "trust" the project before it will open. This is a security measure intended to make people think twice about opening and running random code they find on the Internet, though you can rest assured that there won't be anything malicious about project starting points that I provide in this course.
Having done this, you're ready to begin work. To do that, though, you'll need to know what you need to do, so read on.
The problem
After you've created your PyCharm project, you'll see that it contains two files of immediate interest.
- queens.py, in which you'll find the skeleton of a class named QueensState.
- test_queens.py (in a directory named tests), in which you'll find the skeleton of a unit test class named TestQueensState that is meant to contain unit tests for QueensState.
Your end goal is twofold: Implementing the methods of QueensState class meeting the requirements specified in its docstrings and type annotations, and implementing unit tests of that class in the TestQueensState class.
You might now want to take a look at those two files, so you have an idea of what lies ahead. But it's important that you not barrel forward toward those goals without having read the rest of this project write-up, because there are requirements about how you do this work, in addition to requirements about whether you complete it. While I'm sure all of you have the skills to complete this task in your own chosen way already, there are learning objectives here that have more to do with tools and techniques — which, for most of you, will be a departure from what you're used to — than the code we're asking you to write, which may not be new territory for you at all.
Working and testing incrementally
In your work on this project, we're requiring you to build small-scale features one at a time, and you are required to write unit tests as you go. If you're not feeling sure what I mean by "small-scale feature" here, it might be worth having a look at the notes accompanying the Test-Driven Development topic that I cover in ICS 32 and ICS 32A, which proposes one way to approach this kind of development. In this course, we're not particularly zealous about writing tests before we write code — that's certainly reasonable, but hardly a requirement — but we do at least want to be sure that we're writing tests shortly after writing the code under test, if not before. Whether the tests are written before or after implementing a feature, we want to get a feature nailed down (including its testing) before we move on to the next one; that's mainly where the benefit of this kind of approach arises. And, once we've got it nailed down, we're on demonstrably stable ground, so we should keep a copy of our work at that point in time, for which we'll use a tool called Git.
To give you an example of a small-scale feature you might start with in this project, let's start with this one: "When a QueensState is initially created, its queen_count method will return zero." That's our initial goal and our only goal for now, so we'll focus on that and ignore everything else until later. As it turns out, there's already a unit test for this particular feature provided in test_queens.py, which you'll find in a method named test_queen_count_is_zero_initially. Let's run that test and see it fail, mainly so we know how to run unit tests in PyCharm, which we'll need to do often as we work.
Running unit tests in PyCharm
When you want to run your unit tests within PyCharm, the easiest way to do so is to right-click (or Ctrl-click on macOS) on a test module like test_queens.py, or a directory like tests that contains many of them, and select Run 'Python tests in...'. (That menu item will sometimes have slightly different wording, but will generally begin with Run 'Python tests, even if followed with something else.) This will cause PyCharm to run all of the selected tests and display their results. Because you'll be writing code and tests incrementally, you'll likely find yourself running your tests quite often. It's not uncommon for my develop-test cycle to be no more than a few minutes, or even sometimes less than a minute, depending on the kind of work I'm doing. Frequent actionable feedback about one's progress can be a huge boon to one's productivity, keeping us "in the zone" while leaving behind a lasting record — in the form of our unit tests — of exactly how our program is meant to behave.
Having run the tests, you should see the Run tab in PyCharm's user interface displayed, if it wasn't already. In that tab will be an indication that the test has failed, along with an error message describing that failure. Our next order of business is to make the test succeed, which we can do with a one-line change in queens.py. In the queen_count method, replace the pass statement with return 0 instead. Save your change to queens.py and then re-run the unit tests again, and you should now see that they've passed instead of failing.
Building our historical record in Git
Now that we've got our first feature nailed down — that's really all there is to our first feature, though they won't all be this easy — we're on stable ground, so we now need to note this in our historical record, since one of the requirements of this project is that you submit a complete record of the changes you made, one feature at a time. To do that, though, we'll need to understand a little bit about what Git is, and how we interact with it in PyCharm.
Git is what's often called a version control or source control system, which means that it's in the business of tracking many versions of our source code (i.e., the code that makes up our program) instead of just one. When you created your new PyCharm project using the provided Git repository, it triggered PyCharm to build a Git repository for it automatically, which simply means that there's an additional directory within your project directory named .git — which you may not see, because a lot of operating systems will hide it from you, unless you turn that feature off — that stores a complete history of every version of your project as it evolved. PyCharm recognizes this Git repository automatically and gives us tools for interacting with it visually.
When we want to update the history of our project, we do so by committing a change to our Git repository, which is to say that we instruct Git to remember which files changed and what changed within them, alongside a commit comment that we write explaining whatever else we want to describe about the update we're making. Notably, this doesn't replace what was in the Git repository previously; it augments it. Our Git repository contains the entire history of changes — every commit we've made from beginning to end — which means it contains enough information to allow us to reconstruct every prior version of our project. As long as we made a commit at a particular point in time, we can get back to that point in time quickly and accurately (and non-destructively!), as well as do other useful things, such as finding out the last time a particular file changed, viewing exactly what we changed in a particular commit, or comparing two commits from different points in history to see how they differ.
(When shared amongst groups of people working together on a project, Git shines even more brightly, allowing us to do things like finding out "Who was the last person to change this line of code and when was it?" or ensuring that changes made by one person don't blindly overwrite changes made by someone else. Since your work in this course will be entirely individual, you won't have occasion to experience those benefits in this course, but when it comes time to work in larger teams, you'll be able to expand your knowledge of Git so that it can support you and your teammates in those efforts, as well.)
So, how do we commit our change? Along the left-hand side of the PyCharm window, you should see a column of buttons labeled with icons. It may not be immediately apparent what each icon does, but hovering over the icon will reveal its name. One of the buttons will be named Commit — for me, this one is near the top, though I suspect this is reconfigurable — which you should click. This will reveal an area of the window that lets you stage your changes and commit them. There are two separate areas listing directories and files, one called Staged and the other labeled Unstaged.
The idea behind "staging" is simpler than it sounds. The Unstaged area lists files that are different than they were in the last commit, but for which you haven't affirmatively specified that you want to commit them. The Staged area displays the changes that you've decided you want to commit. (This allows you to work on two things at once, or to commit the things you're surer about without also committing the things still in flight.) So, committing our change is a three-step process.
- Right-click (or Ctrl-click, on macOS) a file listed in the Unstaged area and select Stage from the menu. (You can also right-click a directory, or even the entire Unstaged area, if you want to act on multiple files instead of just one.) This should move the select file(s) from the Unstaged area to the Staged area. (Nothing has moved on your filesystem; this is just changing Git's understanding of what you want to do about a particular change that's already been saved.)
-
When you've staged all of the changes you want to commit, click in the empty area just above the button labeled Commit, which is an area in which you can write a commit comment describing your change. This is where you'd briefly want to describe what's changed and why. Simple changes require less of a comment than larger ones. For this change, it's simple enough that perhaps a comment like Initially, the number of queens is zero is sufficient.
- To follow the usual Git convention, you'll want to write your commit comments to have a short title on the first line of text — no more than 50 or so characters — followed by a blank line, followed by any additional explanation you'd like to write.
- Make sure that the checkbox marked Amend is not checked. Amending a commit is a way of adding a new batch of changes to the most recent commit, which is not what you'd want to do here — but can be useful when you realize that you've left one or more files out of a commit (or accidentally included changes you didn't want to be included) immediately after having made it.
- Now that you're ready to commit your change, click the Commit button. (You won't likely want the Commit and Push button in this course. To push in Git is to share local changes to a Git repository into a remote copy of that same repository stored somewhere online, which can be useful when multiple people are collaborating on the same project, but won't be of much use to us here.)
- PyCharm, at this point, may ask you to type your name and your email address, which is how Git identifies the author of a commit, something that has a lot of value in a team-based project, where it becomes necessary for collaborators to know how to contact one another. From the perspective of this quarter's work, you should fill in the name and UCI email address that we'll recognize as yours — rather than a completely invented name or off-campus email address.
If you don't see separate Staged and Unstaged areas, it's possible that you've somehow adjusted PyCharm's setting governing whether a "staging area" will be in use. (It's also possible that you didn't install this course's PyCharm settings previously.) To solve that problem, you can select Settings from the File menu. (On Windows, the menus are accessible by clicking the menu icon, which is drawn as a series of parallel horizontal lines and shown near the top-left of the window; on macOS, you'll find the application's menu in the usual place.) Along the left-hand side, expand the Version Control settings, then select Git from the list. If the setting named Enable staging area does not have a checkmark next to it, click it so that it does. Then click OK near the bottom-right of the settings window.
When you're done, you can click the icon named Project along the left-hand side of the window to return to the view you had before (i.e., with the files and directories visible again).
Meanwhile, if you click the icon named Git along the lefthand side of the PyCharm window, you should see your new commit listed in your repository's history. Selecting a commit in that history will display which files were changed in that commit and what comment you wrote accompanying the change. Double-clicking one of the files will show you how it changed in that commit (i.e., you'll be able to see what the file looked like both before and after, with a visual indication of where the differences are). This will let you explore your project's history, which can be a very useful tool when you're trying to figure out things like "How was this function written before I overhauled it a few commits ago?" or "When did I last change that method?"
Testing incrementally
While you work, you'll be required to write unit tests. Note, too, that the phrase "while you work" has meaning here; each time you've finished a small feature, it will need to be accompanied at that time by the corresponding unit tests. Ideally, a Git commit that includes a new feature or a fix to existing code would include the applicable changes to the unit tests (i.e., the new or updated tests related to your change), so that each commit is demonstrably stable ground: a finished or fixed feature, along with tests that give you confidence in your assessment that it's finished or fixed. That may be a very different way of working than you're used to, because it requires a level of discipline you might have survived without so far, but working incrementally and testing as you go is a technique that many professional software engineers — me included, as often as I'm able — follow as carefully as possible, because it's one of the many techniques that aid us in tackling substantially larger problems than those we can fit entirely in our heads at any one time.
To reiterate for clarity, following this approach is a requirement and the extent to which you follow this approach constitutes a substantial portion of your grade on this project. While there is certainly leeway in the definition of the word "feature," and we're not going to be able to spend the time negotiating with individual students about exactly how many features are required or exactly which features must be implemented in which order, it is certainly true that students who submit a complete solution with only a small handful of commits, or with tests written only after all features were implemented (or not at all) will find themselves with scores much lower than they would probably expect. Approach the problem incrementally, testing as you go, and you'll be fine from a grade perspective, but you'll also have learned a valuable set of skills that you can use moving forward, ones that I use nearly every day in my professional work.
How many unit tests are required?
You'll need to write as many unit tests as are needed to fully cover its behavior. Your goal for this project is to achieve full coverage, which is to say that at least one test should reach every line of code in queens.py, and that at least one test should exercise every branch in every direction (e.g., an if statement needs to be tested in both the truthy and falsy cases). While that's a more ambitious goal than we'll often be aiming for, the nature of this problem — a class describing a type of immutable object, whose methods have no side effects — is such that we can achieve it with techniques you'll have seen previously, which makes it a great way to learn how to achieve that standard when it's an appropriate one.
Of course, this means that how you choose your tests will have an impact on the number of tests you'll write. Many tests that, when executed, take the same route through your code don't improve the overall coverage measurement at all, which is an indication that having more of them may not be adding any more value than if there were fewer. That's why we're not specifying a number of tests that we're requiring you to write; it doesn't matter how many tests you write if they're all testing the same behavior. It's writing tests with variety that matters, and, fortunately, there's a way to measure that variety.
Measuring code coverage using PyCharm
(Note: To do what's described in this section, you'll need PyCharm Professional. If you installed PyCharm Community instead, the code coverage feature will not be available, but you'll need it from time to time in this course, so you'll want to upgrade to PyCharm Professional before proceeding.)
Code coverage measurement is the practice of running a program in an environment that keeps track of which lines of code were reached, which branches were taken in which directions (e.g., for each if statement, track whether its condition has been both True and False), and so on. Where this technique can be very useful is alongside unit testing. If we measure the level of coverage achieved by running our unit tests, we have a visible indication when there are parts of our code we've not tested at all. While achieving full coverage is not necessarily an indication that every useful test has been written — like any metric, this one can be gamed a bit, so we don't want to turn our brains off and just follow it blindly — the absence of full coverage highlights scenarios that we've certainly not tested.
PyCharm provides the built-in ability to measure code coverage while running tests. The easiest way to do it is to right-click (or Ctrl-click on macOS) on a test module like test_queens.py, or a directory like tests that contains many of them, and select More Run/Debug and then select Run ... with Coverage. (The precise wording on that last menu item will vary, but it'll generally begin with the word Run and end with the words with Coverage.) When we do that, the selected tests run and we see their results, but PyCharm will additionally display coverage statistics in a separate area of the screen. As long as those coverage statistics are visible, opening a Python module like queens.py in the PyCharm editor will also display a visual indication along the left-hand edge of the editor that shows which lines were reached:
- Lines with a green marking were executed completely.
- Lines with a red marking were not reached at all.
- Lines with a yellow marking are branches that were partially executed, which means that not every choice was made. Clicking that yellow marking will briefly explain which branches were taken and which weren't.
- Lines marked with no color have no meaningful code on them (e.g., they're blank or contain nothing but comments).
When you're finished, executing all of your unit tests should lead to every meaningful line (i.e., every line that's not blank or only a comment) in queens.py being marked green. If not, you'll need to evaluate what tests you might need to add — the specific situations you aren't testing already — to achieve that goal.
Importantly, please note that it doesn't matter if the code in test_queens.py is marked green or not. What we're measuring is the extent to which our tests exercise the code being tested, so we only care about the code being tested, which is in queens.py.
Installing coverage.py
The first time you attempt to run you tests in PyCharm with code coverage measurement, you'll likely see an error message indicating the following.
- Coverage is not importable in this environment. Please install coverage.py or enabled 'Use bundled coverage' in Settings | Coverage.
Of these two choices, installing the coverage.py library is the better choice — we've had ongoing problems in my courses with the bundled coverage tool — so your best bet is to click on the word install in that error message, which is a link; if clicked, it will install the package and you'll be off to the races.
Another way to install the package is manually. (There's no need to do this if you used the link described in the previous paragraph, but learning how to install packages is a handy thing, so it might be worth reading through these instructions, anyway.)
- Click the Python Packages icon along the lefthand edge of the PyCharm window. (You might find that it's hidden behind an icon depicted as three dots, which reveals a list of additional icons you can click.) This will reveal an area that allows you to install third-party libraries from the PyPI repository — from which the Python community predominantly downloads its third-party libraries — including coverage.py.
- In the top-left corner of the Python Packages area is a search box; type coverage in it. (PyPI has thousands of packages to choose from, so we'll need to narrow our search.)
- Next, open up PyPI (by clicking the little arrow to its left) so that you can see what's inside of it. Listed below it will be many different packages meeting your search term coverage (i.e., with the word coverage in their name), but you want the one that's just named coverage.
- Click the coverage package in that list, then click the Install package button that you'll see appear near the right-hand side of the Python Packages area.
Once coverage.py is installed, it will be used automatically to determine your code coverage the next time you run your tests with code coverage measurement.
It's worth noting, though, that when you start a new project, this setting may not still be in effect, so you may need to do the following to turn it back on.
- From the File menu, select Settings. (On Windows, the menus are accessible by clicking the menu icon, which is drawn as a series of parallel horizontal lines and shown near the top-left of the window; on macOS, you'll find the application's menu in the usual place.)
- Along the left-hand side, expand the selection named Build, Execution, Deployment.
- Still along the left-hand side, select Coverage.
- If the setting Use bundled coverage.py has a checkmark next to, click it so that it doesn't.
- Click OK near the bottom-right corner of the settings window.
Limitations
You can use the Python standard library where appropriate in this project, and you can certainly depend on the code that we've provided, but you will otherwise not be able to use code written by anyone else other than you. Notably, this includes third-party libraries (i.e., those that are not part of Python's standard library), which are strictly off-limits in this course except where specifically allowed. Colloquially, if we have to install something other than Python, Git, and PyCharm in order for your program to work, it's considered off-limits, unless specific permission is given in a particular project. This project offers no such permission.
Since we'll be automatically testing your QueensState class, rather than relying only on your tests to demonstrate its completeness and correctness, do not modify the Position namedtuple or the provided exception classes (DuplicateQueenError and MissingQueenError), since our automated tests will depend specifically on the way that they're written.
Preparing your submission
Because the grading of many of your assignments will be at least partially automated, we'll need to agree on a submission format, so that everyone's submission will be arranged identically. Fortunately, our use of Git makes this choice simple. Git allows a complete repository to be packaged up into a file called a Git bundle, in a format that Git-compatible tools (like PyCharm) can work with easily; so, you'll provide us with a Git bundle as your final submission. In other words, what you'll be submitting to us is essentially your entire Git repository, including all of the commits you made along the way, so that we have a complete history of your work and how it evolved from the starting point to the finished product.
It's important to understand that it's not our goal to judge every one of your commits, so there's no need to feel uncomfortable about submitting a repository that includes in-progress versions of your work, or to spend time curating a parallel repository of "clean" changes. We completely understand that earlier commits will have warts and rough edges, just as the earlier commits in our own repositories in our own work are of varying quality. For the most part, all we'll be grading in detail is your most recent commit on the main branch of your Git repository. But we do want to be able to see an indication of your process, which can sometimes help us to understand the details of your submission, and can allow us to verify that you had a process, which is among the techniques we want you to learn this quarter, but that can't be learned without doing it.
Demonstrating that you've worked incrementally is a substantial part of your grade, but we don't have precise numeric requirements about how you worked incrementally. There's no predetermined number of commits you must have, or a predetermined number of lines of code that can change between commits. The goal here is qualitative rather than quantitative. All you need to do is follow one simple rule: Each time you've reached stable ground, with a small-scale feature working and tested, or with a problem fixed and a test that identified the problem and now demonstrates that it was fixed, it's time to commit your change with a brief explanation of what new feature you added, or what problem you were fixing. That will benefit you as much as it does us — you'd be surprised how much it helps your thought process to stop and write a couple of sentences about what you're doing and why, and how useful it can be when you're able to refer to your own previous commits — and that's all we're asking for here.
Generating a bundle using the prepare_submission.py script
When you're ready to submit your work, you'll run a script we provided — which you'll find in your project directory — named prepare_submission.py. That script will make an attempt to create a Git bundle from the Git repository in your project directory, which would constitute your entire submission.
The prepare_submission.py script will attempt to verify a few things before it creates a Git bundle, to ensure that it's able to create a bundle, and that you're submitting a complete version of your work.
- It will check that you're running the version of Python we're using in this course, warning you if you aren't. (If you aren't, you might want to be sure your submission works as expected on the correct version of Python before submitting it.)
- It either needs to be able to find your Git installation, or you'll need to tell it where Git can be found (by updating the global constant _GIT_EXECUTABLE_PATH to specify where it is).
- It needs to be run in a directory that contains a Git repository. As long as you created your PyCharm project from our Git bundle using the instructions we've provided, and you haven't rearranged the existing files within that project, that should always be true.
- If there are uncommitted changes in your project directory (e.g., you've added, updated, or removed one or more files, but that change hasn't been committed), it will warn you, and you'll likely want to commit those changes (or roll them back) before you create your bundle for submission, so that your submission will be synchronized with the code in your project directory.
Running the prepare_submission.py is a simple matter of right-clicking it (or Ctrl-clicking it, on macOS), and selecting Run 'prepare_submission'. The Run area in the PyCharm window should be displayed, and any output from the script — including any warnings or error messages — will be displayed there. Assuming there are no warnings or errors, you'll find the file project0.bundle in your project directory, and that's the one and only file you'd submit.
Verifying your bundle before submission
Before you submit your bundle, you'll likely want to verify that it's complete and correct. Note that you bear the risk here, which is to say that we'll be grading what you submit, and you won't later be able to explain that you would have preferred to submit something else. So, now's the time to be sure that what you're submitting is what you want us to grade.
The best way to verify your bundle prior to submitting it is to create a new PyCharm project from your bundle, so you can most easily see what's in it. There are a couple of ways to do that, depending on what operating system you're using.
- On Windows, PyCharm is able to open Git bundles directly. So, you can create a new PyCharm project by following the same steps you used when starting the project, but specifying the path to your bundle when asked to specify a URL. (You'll want to create this project in a different directory from your project directory, so it's separate and isolated.)
-
On macOS and Linux, PyCharm will not be able to create PyCharm projects from Git bundles. The workaround is to create a new Git repository from your bundle manually, then create a project from that. Open a Terminal window and type these commands, filling in the path to the bundle you created where specified:
cd ~ mkdir -p temp cd temp git clone PATH_TO_THE_BUNDLE_YOU_CREATED
Your home directory will now contain a directory named temp, which will contain a directory with the name of your bundle. You can now create a new PyCharm project by following the same steps you used when starting the project, but specifying the path to the directory containing the new copy of your repository that you just created.
Afterward, you should see the files in their final form, and the Git tab in PyCharm should show your entire commit history. Be sure, too, that the main branch is where you want it to be — that's what we'll be grading. If so, you're in business; go ahead and submit your work.
Deliverables
Submit your project0.bundle file (and no others) to Canvas. There are a few rules to be aware of.
- When grading your program, we'll grade only the most recent submission. We will not negotiate about which submission will be graded, or, for example, grade multiple of your submissions and "take the highest score."
- When grading your program, we'll grade only the most recent commit on the main branch, except to the extent that we'll examine prior commits when evaluating your overall process. We will not negotiate about which commit will be graded, or, for example, grade multiple of your commits and "take the highest score."
- You're responsible for submitting the version of your project that you want graded prior to the deadline. Contacting us afterward and telling us that you accidentally submitted the wrong version will not be grounds for a resubmission under any circumstances.
- You're responsible for making a submission in order to receive credit, which means you'll want to be sure that you've remembered to submit your work and verify in Canvas that it's been received. A later claim of having forgotten to submit your work or having misremembered the due date will not be grounds for a resubmission under any circumstances.
- The determination of whether your work has been submitted before the deadline is the time it was submitted to Canvas. Neither timestamps on local copies of your files nor timestamps on commits in your Git repository or in other places (e.g., emails or online storage) are considered evidence of completion prior to the deadline under any circumstances.
Can I submit after the deadline?
This project is not included in the late work policy for this course. The objective is not just that you do this one, but that you do it early enough to be of benefit, so it needs to be completed during the initial days of the course and submitted before the due date above. Submissions beyond that deadline will not be considered under any circumstances.
The late work policy for this course — which does not apply to this project, but applies to all of the others — is described in the section titled Late work at this link.
What do I do if Canvas adjusts my filename?
Canvas will sometimes modify your filenames when you submit them (e.g., by adding a numbering scheme like -1 or a long sequence of hexadecimal digits to its name). In general, this is fine; as long as the file you submitted has the correct name prior to submission, we'll be able to obtain it with that same name, even if Canvas adjusts it.