Repository: Btibert3/pypeds (language: python)

Issue:
Write unit tests for loader classes
To make other code changes easier, we should add unit tests for the loader classes in `pypeds/ipeds.py` (e.g., `HD()`, `IC()`). These will test the `__init__`, `extract`, `load`, and `transform` methods of each class.


Discussion / hints:

Fix patch:
diff --git a/requirements.txt b/requirements.txt
index 80ae326..444e7c4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,20 +4,26 @@ certifi==2022.12.7
 charset-normalizer==3.0.1
 dfply==0.3.3
 entrypoints==0.4
+exceptiongroup==1.1.0
 idna==3.4
+iniconfig==2.0.0
 Jinja2==3.1.2
 jsonschema==4.17.3
 MarkupSafe==2.1.2
 numpy==1.24.2
+packaging==23.0
 pandas==1.5.3
 pantab>=2.1.0
+pluggy==1.0.0
 pyrsistent==0.19.3
 python-dateutil==2.8.2
+pytest==7.2.1
 pytz==2022.7.1
 requests==2.28.2
 setuptools==65.5.1
 six==1.16.0
 tableauhyperapi==0.0.14401
+tomli==2.0.1
 toolz==0.12.0
 urllib3==1.26.14
 xlrd==2.0.1


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/static/adm2020.csv b/tests/static/adm2020.csv
new file mode 100644
index 0000000..631fc51
--- /dev/null
+++ b/tests/static/adm2020.csv
@@ -0,0 +1,3 @@
+UNITID,ADMCON1,ADMCON2,ADMCON3,ADMCON4,ADMCON5,ADMCON6,ADMCON7,ADMCON8,ADMCON9,XAPPLCN,APPLCN,XAPPLCNM,APPLCNM,XAPPLCNW,APPLCNW,XADMSSN,ADMSSN,XADMSSNM,ADMSSNM,XADMSSNW,ADMSSNW,XENRLT,ENRLT,XENRLM,ENRLM,XENRLW,ENRLW,XENRLFT,ENRLFT,XENRLFTM,ENRLFTM,XENRLFTW,ENRLFTW,XENRLPT,ENRLPT,XENRLPTM,ENRLPTM,XENRLPTW,ENRLPTW,XSATNUM,SATNUM,XSATPCT,SATPCT,XACTNUM,ACTNUM,XACTPCT,ACTPCT,XSATVR25,SATVR25,XSATVR75,SATVR75,XSATMT25,SATMT25,XSATMT75,SATMT75,XACTCM25,ACTCM25,XACTCM75,ACTCM75,XACTEN25,ACTEN25,XACTEN75,ACTEN75,XACTMT25,ACTMT25,XACTMT75,ACTMT75 
+100654,1,2,1,2,3,2,1,1,3,"R",9855,"R",3394,"R",6461,"R",8835,"R",2947,"R",5888,"R",1664,"R",676,"R",988,"R",1622,"R",660,"R",962,"R",42,"R",16,"R",26,"R",22,"R",1,"R",1202,"R",72,"R",430,"R",520,"R",410,"R",500,"R",15,"R",20,"R",14,"R",20,"R",15,"R",18
+100663,1,3,1,1,3,3,1,3,3,"R",10391,"R",3803,"R",6588,"R",8375,"R",3002,"R",5373,"R",2154,"R",765,"R",1389,"R",2102,"R",738,"R",1364,"R",52,"R",27,"R",25,"R",302,"R",14,"R",2120,"R",98,"R",560,"R",668,"R",530,"R",660,"R",22,"R",30,"R",22,"R",33,"R",20,"R",27
diff --git a/tests/static/c2020_a.csv b/tests/static/c2020_a.csv
new file mode 100644
index 0000000..4c0f3dd
--- /dev/null
+++ b/tests/static/c2020_a.csv
@@ -0,0 +1,3 @@
+UNITID,CIPCODE,MAJORNUM,AWLEVEL,XCTOTALT,CTOTALT,XCTOTALM,CTOTALM,XCTOTALW,CTOTALW,XCAIANT,CAIANT,XCAIANM,CAIANM,XCAIANW,CAIANW,XCASIAT,CASIAT,XCASIAM,CASIAM,XCASIAW,CASIAW,XCBKAAT,CBKAAT,XCBKAAM,CBKAAM,XCBKAAW,CBKAAW,XCHISPT,CHISPT,XCHISPM,CHISPM,XCHISPW,CHISPW,XCNHPIT,CNHPIT,XCNHPIM,CNHPIM,XCNHPIW,CNHPIW,XCWHITT,CWHITT,XCWHITM,CWHITM,XCWHITW,CWHITW,XC2MORT,C2MORT,XC2MORM,C2MORM,XC2MORW,C2MORW,XCUNKNT,CUNKNT,XCUNKNM,CUNKNM,XCUNKNW,CUNKNW,XCNRALT,CNRALT,XCNRALM,CNRALM,XCNRALW,CNRALW  
+100654,"01.0999",1,05,"R",3,"Z",0,"R",3,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",2,"Z",0,"R",2,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",1,"Z",0,"R",1,"Z",0,"Z",0,"Z",0
+100654,"01.1001",1,05,"R",7,"R",2,"R",5,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",7,"R",2,"R",5,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0
diff --git a/tests/static/ef2017c.csv b/tests/static/ef2017c.csv
new file mode 100644
index 0000000..6fdadd8
--- /dev/null
+++ b/tests/static/ef2017c.csv
@@ -0,0 +1,3 @@
+UNITID,EFCSTATE,LINE,XEFRES01,EFRES01,XEFRES02,EFRES02 
+100654, 1,  1,"R",667,"R",524
+100654, 5,  5,"R",7,"R",6
diff --git a/tests/static/ef2017d.csv b/tests/static/ef2017d.csv
new file mode 100644
index 0000000..4a6ae6c
--- /dev/null
+++ b/tests/static/ef2017d.csv
@@ -0,0 +1,3 @@
+UNITID,XGRCOHRT,GRCOHRT,XUGENTER,UGENTERN,XPGRCOHR,PGRCOHRT,XRRFTCT,RRFTCT,XRRFTEX,RRFTEX,XRRFTIN,RRFTIN,XRRFTCTA,RRFTCTA,XRET_NMF,RET_NMF,XRET_PCF,RET_PCF,XRRPTCT,RRPTCT,XRRPTEX,RRPTEX,XRRPTIN,RRPTIN,XRRPTCTA,RRPTCTA,XRET_NMP,RET_NMP,XRET_PCP,RET_PCP,XSTUFACR,STUFACR 
+100654,"R",1288,"R",1604,"R",80,"R",1410,"R",0,"R",0,"R",1410,"R",829,"R",59,"R",38,"R",0,"R",0,"R",38,"R",5,"R",13,"R",18
+100663,"R",2228,"R",3964,"R",56,"R",1931,"R",0,"R",0,"R",1931,"R",1629,"R",84,"R",73,"R",0,"R",0,"R",73,"R",32,"R",44,"R",19
diff --git a/tests/static/f1920_f1a.csv b/tests/static/f1920_f1a.csv
new file mode 100644
index 0000000..cfa7bf6
--- /dev/null
+++ b/tests/static/f1920_f1a.csv
@@ -0,0 +1,3 @@
+UNITID,XF1A01,F1A01,XF1A31,F1A31,XF1A04,F1A04,XF1A05,F1A05,XF1A06,F1A06,XF1A19,F1A19,XF1A07,F1A07,XF1A08,F1A08,XF1A09,F1A09,XF1A10,F1A10,XF1A11,F1A11,XF1A12,F1A12,XF1A13,F1A13,XF1A20,F1A20,XF1A14,F1A14,XF1A15,F1A15,XF1A16,F1A16,XF1A17,F1A17,XF1A18,F1A18,XF1A214,F1A214,XF1A224,F1A224,XF1A234,F1A234,XF1A324,F1A324,XF1A274,F1A274,XF1A27T4,F1A27T4,XF1A284,F1A284,XF1A334,F1A334,XF1A344,F1A344,XF1D01,F1D01,XF1D02,F1D02,XF1D03,F1D03,XF1D04,F1D04,XF1D05,F1D05,XF1D06,F1D06,XF1B01,F1B01,XF1B02,F1B02,XF1B03,F1B03,XF1B04,F1B04,XF1B04A,F1B04A,XF1B04B,F1B04B,XF1B05,F1B05,XF1B06,F1B06,XF1B26,F1B26,XF1B07,F1B07,XF1B08,F1B08,XF1B09,F1B09,XF1B10,F1B10,XF1B11,F1B11,XF1B12,F1B12,XF1B13,F1B13,XF1B14,F1B14,XF1B15,F1B15,XF1B16,F1B16,XF1B17,F1B17,XF1B18,F1B18,XF1B19,F1B19,XF1B27,F1B27,XF1B20,F1B20,XF1B21,F1B21,XF1B22,F1B22,XF1B23,F1B23,XF1B24,F1B24,XF1B25,F1B25,XF1C011,F1C011,XF1C012,F1C012,XF1C021,F1C021,XF1C022,F1C022,XF1C031,F1C031,XF1C032,F1C032,XF1C051,F1C051,XF1C052,F1C052,XF1C061,F1C061,XF1C062,F1C062,XF1C071,F1C071,XF1C072,F1C072,XF1C101,F1C101,XF1C111,F1C111,XF1C112,F1C112,XF1C121,F1C121,XF1C122,F1C122,XF1C131,F1C131,XF1C132,F1C132,XF1C141,F1C141,XF1C142,F1C142,XF1C191,F1C191,XF1C192,F1C192,XF1C193,F1C193,XF1C19OM,F1C19OM,XF1C19DP,F1C19DP,XF1C19IN,F1C19IN,XF1C19OT,F1C19OT,F1MHP,XF1M01,F1M01,XF1M02,F1M02,XF1M03,F1M03,XF1M04,F1M04,F1MHOP,XF1M05,F1M05,XF1M06,F1M06,XF1M07,F1M07,XF1M08,F1M08,XF1E01,F1E01,XF1E02,F1E02,XF1E03,F1E03,XF1E04,F1E04,XF1E05,F1E05,XF1E06,F1E06,XF1E07,F1E07,XF1E08,F1E08,XF1E09,F1E09,XF1E10,F1E10,XF1E11,F1E11,XF1E12,F1E12,XF1E121,F1E121,XF1E122,F1E122,XF1E13,F1E13,XF1E131,F1E131,XF1E132,F1E132,XF1E14,F1E14,XF1E141,F1E141,XF1E142,F1E142,XF1E15,F1E15,XF1E151,F1E151,XF1E152,F1E152,XF1E16,F1E16,XF1E161,F1E161,XF1E162,F1E162,XF1E17,F1E17,XF1E171,F1E171,XF1E172,F1E172,F1FHA,XF1H01,F1H01,XF1H02,F1H02,XF1H03,F1H03,XF1H03A,F1H03A,XF1H03B,F1H03B,XF1H03C,F1H03C,XF1H03D,F1H03D,XF1N01,F1N01,XF1N02,F1N02,XF1N03,F1N03,XF1N04,F1N04,XF1N05,F1N05,XF1N06,F1N06,XF1N07,F1N07   
+100654,"R",113462225,"R",164978439,"R",0,"R",164978439,"R",278440664,"R",20470855,"R",4488644,"R",73922593,"R",78411237,"R",79607043,"R",105010519,"R",184617562,"R",263028799,"R",32910420,"R",80882752,"R",0,"R",914144,"R",-78824596,"R",2972300,"R",5598192,"R",0,"R",230093529,"R",40964928,"R",23168141,"R",299824790,"R",139539403,"R",0,"R",4693051,"R",182077358,"R",162897947,"R",19179411,"R",-17411077,"R",1203966,"R",2972300,"R",50395005,"R",31871284,"R",970617,"R",342681,"R",0,"R",342681,"R",25675605,"R",0,"R",2245068,"R",0,"R",110731,"R",111610991,"R",3121777,"R",46717823,"R",0,"R",19102421,"R",176182,"R",0,"R",440000,"R",233164,"R",0,"R",69791367,"R",181402358,"R",675000,"R",0,"R",0,"R",0,"R",675000,"R",182077358,"R",30084991,"R",23131805,"R",9206031,"R",4948571,"R",11497156,"R",6082387,"R",7257779,"R",4136508,"R",27527791,"R",8257832,"R",10493154,"R",7346472,"R",23145252,"R",13413035,"R",1115980,"R",0,"R",0,"R",0,"R",0,"R",30272758,"R",6188,"R",162897947,"R",55025743,"R",13186701,"R",32304586,"R",6898447,"R",2701970,"R",52780500,1 ,"R",8452973,"R",79704000,"R",2964000,"R",15042334,1 ,"R",3823395,"R",22585851,"R",29946420,"R",3587069,"R",18427393,"R",675028,"R",176182,"R",0,"R",0,"R",26851717,"R",46130320,"R",22985068,"R",0,"R",22985068,"R",23145252,"R",0,"R",0,"R",0,"R",106420,"R",106420,"R",0,"R",44332,"R",44332,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",22834316,"R",22834316,"R",0,2 ,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"R",-17695164,"R",182077358,"R",19179411,"R",-16207111,"R",-78824596,"R",84095687,"R",162897947
+100663,"R",2275161243,"R",1780283860,"R",1503358031,"R",3283641891,"R",5558803134,"R",318830730,"R",38749671,"R",735642989,"R",774392660,"R",1087186699,"R",1552812605,"R",2639999304,"R",3414391964,"R",521937116,"R",765335216,"R",353055159,"R",405515948,"R",417398461,"R",1941304784,"R",170128180,"R",99616819,"R",2779902251,"R",1097695923,"R",44498064,"R",4191841237,"R",2411557377,"R",0,"R",0,"R",3474561258,"R",3316705873,"R",157855385,"R",1761851610,"R",21597789,"R",1941304784,"R",244929737,"R",392328131,"R",9637192,"R",81956259,"R",2743274,"R",79212985,"R",40269522,"R",2109833577,"R",59351275,"R",0,"R",51986550,"R",2990292243,"R",71281070,"R",306964712,"R",0,"R",57528004,"R",328585,"R",0,"R",18705016,"R",5169229,"R",3690454,"R",463667070,"R",3453959313,"R",0,"R",1854223,"R",17755898,"R",991824,"R",20601945,"R",3474561258,"R",300215187,"R",200836345,"R",302659583,"R",145613167,"R",184918390,"R",86773578,"R",173773607,"R",127432185,"R",40974834,"R",22132005,"R",220207623,"R",68921533,"R",35285313,"R",79414333,"R",15930599,"R",1892254393,"R",677699115,"R",0,"R",0,"R",87002610,"R",0,"R",3316705873,"R",1345338527,"R",333155173,"R",82380072,"R",141290967,"R",35437969,"R",1379103165,1 ,"R",112188000,"R",1245083000,"R",90170000,"R",198607000,1 ,"R",-25185389,"R",271431941,"R",431767116,"R",106887017,"R",23943357,"R",21881772,"R",304826,"R",44643,"R",10753136,"R",66244612,"R",123172346,"R",85456029,"R",2431004,"R",87887033,"R",35285313,"R",17473476,"R",17473476,"R",0,"R",11542367,"R",11542367,"R",0,"R",222457,"R",222457,"R",0,"R",32580,"R",32580,"R",0,"R",6252650,"R",6252650,"R",0,"R",52363503,"R",49932499,"R",2431004,1 ,"R",537349307,"R",539858544,"R",2509237,"R",26904149,"R",-24394912,"R",0,"R",0,"R",150898087,"R",4268321458,"R",170508208,"R",4074293914,"R",1144733918,"R",63098687,"R",4114622690
diff --git a/tests/static/f1920_f2.csv b/tests/static/f1920_f2.csv
new file mode 100644
index 0000000..1b1a4c4
--- /dev/null
+++ b/tests/static/f1920_f2.csv
@@ -0,0 +1,3 @@
+UNITID,XF2A01,F2A01,XF2A19,F2A19,XF2A20,F2A20,XF2A02,F2A02,XF2A03,F2A03,XF2A03A,F2A03A,XF2A04,F2A04,XF2A05,F2A05,XF2A05A,F2A05A,XF2A05B,F2A05B,XF2A06,F2A06,XF2A11,F2A11,XF2A12,F2A12,XF2A13,F2A13,XF2A15,F2A15,XF2A16,F2A16,XF2A17,F2A17,XF2A18,F2A18,XF2B01,F2B01,XF2B02,F2B02,XF2B03,F2B03,XF2B04,F2B04,XF2B05,F2B05,XF2B06,F2B06,XF2B07,F2B07,XF2C01,F2C01,XF2C02,F2C02,XF2C03,F2C03,XF2C04,F2C04,XF2C05,F2C05,XF2C06,F2C06,XF2C07,F2C07,XF2C08,F2C08,XF2C09,F2C09,XF2C10,F2C10,XF2C12,F2C12,XF2C121,F2C121,XF2C122,F2C122,XF2C13,F2C13,XF2C131,F2C131,XF2C132,F2C132,XF2C14,F2C14,XF2C141,F2C141,XF2C142,F2C142,XF2C15,F2C15,XF2C151,F2C151,XF2C152,F2C152,XF2C16,F2C16,XF2C161,F2C161,XF2C162,F2C162,XF2C17,F2C17,XF2C171,F2C171,XF2C172,F2C172,XF2D01,F2D01,XF2D012,F2D012,XF2D013,F2D013,XF2D014,F2D014,XF2D02,F2D02,XF2D022,F2D022,XF2D023,F2D023,XF2D024,F2D024,XF2D03,F2D03,XF2D032,F2D032,XF2D033,F2D033,XF2D034,F2D034,XF2D04,F2D04,XF2D042,F2D042,XF2D043,F2D043,XF2D044,F2D044,XF2D05,F2D05,XF2D052,F2D052,XF2D053,F2D053,XF2D054,F2D054,XF2D06,F2D06,XF2D062,F2D062,XF2D063,F2D063,XF2D064,F2D064,XF2D07,F2D07,XF2D072,F2D072,XF2D073,F2D073,XF2D074,F2D074,XF2D08,F2D08,XF2D082,F2D082,XF2D083,F2D083,XF2D084,F2D084,XF2D08A,F2D08A,XF2D082A,F2D082A,XF2D083A,F2D083A,XF2D084A,F2D084A,XF2D08B,F2D08B,XF2D082B,F2D082B,XF2D083B,F2D083B,XF2D084B,F2D084B,XF2D09,F2D09,XF2D092,F2D092,XF2D093,F2D093,XF2D094,F2D094,XF2D10,F2D10,XF2D102,F2D102,XF2D103,F2D103,XF2D104,F2D104,XF2D11,F2D11,XF2D112,F2D112,XF2D12,F2D12,XF2D122,F2D122,XF2D13,F2D13,XF2D132,F2D132,XF2D14,F2D14,XF2D142,F2D142,XF2D143,F2D143,XF2D144,F2D144,XF2D15,F2D15,XF2D152,F2D152,XF2D153,F2D153,XF2D154,F2D154,XF2D16,F2D16,XF2D162,F2D162,XF2D163,F2D163,XF2D164,F2D164,XF2D17,F2D17,XF2D172,F2D172,XF2D173,F2D173,XF2D174,F2D174,XF2D18,F2D18,XF2D182,F2D182,XF2D183,F2D183,XF2D184,F2D184,XF2E011,F2E011,XF2E012,F2E012,XF2E021,F2E021,XF2E022,F2E022,XF2E031,F2E031,XF2E032,F2E032,XF2E041,F2E041,XF2E042,F2E042,XF2E051,F2E051,XF2E052,F2E052,XF2E061,F2E061,XF2E062,F2E062,XF2E071,F2E071,XF2E072,F2E072,XF2E081,F2E081,XF2E091,F2E091,XF2E092,F2E092,XF2E101,F2E101,XF2E102,F2E102,XF2E121,F2E121,XF2E122,F2E122,XF2E131,F2E131,XF2E132,F2E132,XF2E133,F2E133,XF2E134,F2E134,XF2E135,F2E135,XF2E136,F2E136,XF2E137,F2E137,F2FHA,XF2H01,F2H01,XF2H02,F2H02,XF2H03,F2H03,XF2H03A,F2H03A,XF2H03B,F2H03B,XF2H03C,F2H03C,XF2H03D,F2H03D,XF2I01,F2I01,XF2I02,F2I02,XF2I03,F2I03,XF2I04,F2I04,XF2I05,F2I05,XF2I06,F2I06,XF2I07,F2I07   
+100690,"R",9216811,"R",2815287,"Z",0,"R",15207430,"R",1055058,"R",0,"R",13636478,"R",515894,"R",174818,"R",341076,"R",14152372,"R",1340626,"R",1065662,"R",2991769,"Z",0,"Z",0,"R",5398057,"R",2582770,"R",9188606,"R",6987409,"R",0,"R",2201197,"R",11951175,"R",0,"R",14152372,"R",1263175,"R",23360,"Z",0,"Z",0,"Z",0,"R",1319828,"R",2606363,"R",1319828,"R",0,"R",1319828,"R",1263175,"R",1263175,"R",0,"R",23360,"R",23360,"Z",0,"R",0,"Z",0,"Z",0,"R",0,"Z",0,"Z",0,"R",0,"Z",0,"Z",0,"R",33293,"R",33293,"R",0,"R",8417205,"R",8417205,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",22250,"R",22250,"R",0,"R",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",659208,"R",656568,"R",2640,"R",0,"R",659208,"R",656568,"R",2640,"R",0,"R",0,"R",0,"R",0,"R",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",23124,"R",23111,"R",13,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",66819,"R",262626,"R",-222726,"R",26919,"R",9188606,"R",9381760,"R",-220073,"R",26919,"R",0,"R",0,"Z",0,"Z",0,"R",9188606,"R",9381760,"R",-220073,"R",26919,"R",2220536,"R",1660977,"R",0,"R",0,"R",0,"R",0,"R",650260,"R",505662,"R",1075444,"R",871112,"R",3028885,"R",1079543,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",12284,"R",0,"R",6987409,"R",4117294,"R",520937,"R",80585,"R",144914,"R",11783,"R",2111896, 1,"R",174805,"R",174818,"R",13,"R",0,"R",13,"R",0,"R",0,"R",2394351,"R",9381760,"R",2201197,"R",11951175,"R",14152372,"R",0,"R",6987409
+100937,"R",41963466,"R",87186911,"Z",0,"R",150253116,"R",46263992,"R",31790881,"R",49628822,"R",54360302,"R",5802469,"R",48557833,"R",103989124,"R",25314515,"R",153851504,"R",30875366,"Z",0,"Z",0,"R",210041385,"R",122854474,"R",37079363,"R",44619283,"R",0,"R",-7539920,"R",111529044,"R",0,"R",103989124,"R",1333126,"R",1312194,"Z",0,"Z",0,"R",5427823,"R",5450922,"R",13524065,"R",10878745,"R",0,"R",10878745,"R",0,"R",0,"R",0,"R",1069865,"R",1069865,"Z",0,"R",0,"Z",0,"Z",0,"R",4317306,"R",4317306,"Z",0,"R",0,"Z",0,"Z",0,"R",5491574,"R",5491574,"R",0,"R",10883516,"R",10883516,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",5608848,"R",5608848,"R",0,"R",0,"R",2135,"R",2135,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",4349405,"R",1708831,"R",2042720,"R",597854,"R",4094895,"R",1454321,"R",2042720,"R",597854,"R",254510,"R",254510,"R",0,"R",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",1038409,"R",16660,"R",1006739,"R",15010,"Z",0,"Z",0,"R",13550701,"R",13550701,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"Z",0,"R",1646349,"R",1092333,"R",554016,"R",0,"R",37079363,"R",32863024,"R",3603475,"R",612864,"R",0,"R",8330172,"R",-8330172,"Z",0,"R",37079363,"R",41193196,"R",-4726697,"R",612864,"R",14408312,"R",9052406,"Z",0,"Z",0,"Z",0,"Z",0,"R",3760960,"R",676251,"R",8950139,"R",4013476,"R",8674844,"R",3763270,"R",8522716,"R",593619,"R",302312,"Z",0,"Z",0,"Z",0,"Z",0,"R",0,"R",0,"R",44619283,"R",18099022,"R",4208662,"R",5304911,"R",2810144,"R",1788224,"R",12408320, 1,"R",53117638,"R",49403369,"R",-3714269,"R",723856,"R",1006739,"R",5444864,"R",-10889728,"R",-6024836,"R",39799160,"R",-7539920,"R",111529044,"R",-4126246,"R",31790881,"R",44619283
diff --git a/tests/static/hd2020.csv b/tests/static/hd2020.csv
new file mode 100644
index 0000000..72524db
--- /dev/null
+++ b/tests/static/hd2020.csv
@@ -0,0 +1,3 @@
+UNITID,INSTNM,IALIAS,ADDR,CITY,STABBR,ZIP,FIPS,OBEREG,CHFNM,CHFTITLE,GENTELE,EIN,DUNS,OPEID,OPEFLAG,WEBADDR,ADMINURL,FAIDURL,APPLURL,NPRICURL,VETURL,ATHURL,DISAURL,SECTOR,ICLEVEL,CONTROL,HLOFFER,UGOFFER,GROFFER,HDEGOFR1,DEGGRANT,HBCU,HOSPITAL,MEDICAL,TRIBAL,LOCALE,OPENPUBL,ACT,NEWID,DEATHYR,CLOSEDAT,CYACTIVE,POSTSEC,PSEFLAG,PSET4FLG,RPTMTH,INSTCAT,C18BASIC,C18IPUG,C18IPGRD,C18UGPRF,C18ENPRF,C18SZSET,C15BASIC,CCBASIC,CARNEGIE,LANDGRNT,INSTSIZE,F1SYSTYP,F1SYSNAM,F1SYSCOD,CBSA,CBSATYPE,CSA,NECTA,COUNTYCD,COUNTYNM,CNGDSTCD,LONGITUD,LATITUDE,DFRCGID,DFRCUSCG
+100654,"Alabama A & M University","AAMU","4900 Meridian Street","Normal","AL","35762", 1, 5,"Dr. Andrew Hugine, Jr.","President","2563725000","636001109","197216455","00100200",1,"www.aamu.edu/","https://www.aamu.edu/admissions-aid/index.html","https://www.aamu.edu/admissions-aid/financial-aid/","https://www.aamu.edu/admissions-aid/undergraduate-admissions/apply-today.html","www.aamu.edu/admissions-aid/tuition-fees/net-price-calculator.html"," "," ","https://www.aamu.edu/administrativeoffices/VADS/Pages/Disability-Services.aspx",1,1,1,9,1,1,12,1,1,2,2,2,12,1,"A ",-2,-2,"-2",1,1,1,1,1,2,18,16,17,10,4,14,18,18,16,1,3,2,"-2","-2",26620,1,290,-2,1089,"Madison County",105,-86.568502,34.783368,109,1
+100663,"University of Alabama at Birmingham"," ","Administration Bldg Suite 1070","Birmingham","AL","35294-0110", 1, 5,"Ray L. Watts","President","2059344011","636005396","063690705","00105200",1,"https://www.uab.edu/","https://www.uab.edu/students/admissions/","https://www.uab.edu/students/paying-for-college","https://ssb.it.uab.edu/pls/sctprod/zsapk003_ug_web_appl.new_user","https://uab.studentaidcalculator.com/survey.aspx","https://www.uab.edu/students/veterans","https://www.uab.edu/registrar/students","https://www.uab.edu/students/disability/",1,1,1,9,1,1,11,1,2,1,1,2,12,1,"A ",-2,-2,"-2",1,1,1,1,1,2,15,17,17,9,5,15,15,15,15,2,5,1,"The University of Alabama System","101050",13820,1,142,-2,1073,"Jefferson County",107,-86.799345,33.505697,95,1
diff --git a/tests/static/ic2009_ay.csv b/tests/static/ic2009_ay.csv
new file mode 100644
index 0000000..87d4125
--- /dev/null
+++ b/tests/static/ic2009_ay.csv
@@ -0,0 +1,3 @@
+UNITID,XTUIT1,TUITION1,XFEE1,FEE1,XHRCHG1,HRCHG1,XCMPFEE1,CMPFEE1,XTUIT2,TUITION2,XFEE2,FEE2,XHRCHG2,HRCHG2,XCMPFEE2,CMPFEE2,XTUIT3,TUITION3,XFEE3,FEE3,XHRCHG3,HRCHG3,XCMPFEE3,CMPFEE3,XTUIT5,TUITION5,XFEE5,FEE5,XHRCHG5,HRCHG5,XTUIT6,TUITION6,XFEE6,FEE6,XHRCHG6,HRCHG6,XTUIT7,TUITION7,XFEE7,FEE7,XHRCHG7,HRCHG7,XCHG1AT0,CHG1AT0,XCHG1AF0,CHG1AF0,XCHG1AY0,CHG1AY0,XCHG1AT1,CHG1AT1,XCHG1AF1,CHG1AF1,XCHG1AY1,CHG1AY1,XCHG1AT2,CHG1AT2,XCHG1AF2,CHG1AF2,XCHG1AY2,CHG1AY2,XCHG1AT3,CHG1AT3,XCHG1AF3,CHG1AF3,XCHG1AY3,CHG1AY3,CHG1TGTD,CHG1FGTD,XCHG2AT0,CHG2AT0,XCHG2AF0,CHG2AF0,XCHG2AY0,CHG2AY0,XCHG2AT1,CHG2AT1,XCHG2AF1,CHG2AF1,XCHG2AY1,CHG2AY1,XCHG2AT2,CHG2AT2,XCHG2AF2,CHG2AF2,XCHG2AY2,CHG2AY2,XCHG2AT3,CHG2AT3,XCHG2AF3,CHG2AF3,XCHG2AY3,CHG2AY3,CHG2TGTD,CHG2FGTD,XCHG3AT0,CHG3AT0,XCHG3AF0,CHG3AF0,XCHG3AY0,CHG3AY0,XCHG3AT1,CHG3AT1,XCHG3AF1,CHG3AF1,XCHG3AY1,CHG3AY1,XCHG3AT2,CHG3AT2,XCHG3AF2,CHG3AF2,XCHG3AY2,CHG3AY2,XCHG3AT3,CHG3AT3,XCHG3AF3,CHG3AF3,XCHG3AY3,CHG3AY3,CHG3TGTD,CHG3FGTD,XCHG4AY0,CHG4AY0,XCHG4AY1,CHG4AY1,XCHG4AY2,CHG4AY2,XCHG4AY3,CHG4AY3,XCHG5AY0,CHG5AY0,XCHG5AY1,CHG5AY1,XCHG5AY2,CHG5AY2,XCHG5AY3,CHG5AY3,XCHG6AY0,CHG6AY0,XCHG6AY1,CHG6AY1,XCHG6AY2,CHG6AY2,XCHG6AY3,CHG6AY3,XCHG7AY0,CHG7AY0,XCHG7AY1,CHG7AY1,XCHG7AY2,CHG7AY2,XCHG7AY3,CHG7AY3,XCHG8AY0,CHG8AY0,XCHG8AY1,CHG8AY1,XCHG8AY2,CHG8AY2,XCHG8AY3,CHG8AY3,XCHG9AY0,CHG9AY0,XCHG9AY1,CHG9AY1,XCHG9AY2,CHG9AY2,XCHG9AY3,CHG9AY3,XCMP1AY0,CMP1AY0,XCMP1AY1,CMP1AY1,XCMP1AY2,CMP1AY2,XCMP1AY3,CMP1AY3,CMP1GTD,XCMP2AY0,CMP2AY0,XCMP2AY1,CMP2AY1,XCMP2AY2,CMP2AY2,XCMP2AY3,CMP2AY3,CMP2GTD,XCMP3AY0,CMP3AY0,XCMP3AY1,CMP3AY1,XCMP3AY2,CMP3AY2,XCMP3AY3,CMP3AY3,CMP3GTD 
+100636,"R",0,"R",0,"R",0,"A",.,"R",0,"Z",0,"R",0,"A",.,"R",0,"Z",0,"R",0,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,.,.,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,.,.,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,"B",.,"B",.,"R",0,.,.,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"R",0,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,"A",.,-2,"A",.,"A",.,"A",.,"A",.,-2,"A",.,"A",.,"A",.,"A",.,-2,
+100654,"R",3948,"R",744,"R",165,"A",.,"R",3948,"R",744,"R",165,"A",.,"R",7896,"R",744,"R",329,"A",.,"R",4514,"R",744,"R",251,"R",4514,"R",744,"R",251,"R",9031,"R",744,"R",502,"R",3432,"R",640,"R",4072,"R",3432,"R",640,"R",4072,"R",3432,"R",640,"R",4072,"R",3948,"R",744,"R",4692,.,.,"R",3432,"R",640,"R",4072,"R",3432,"R",640,"R",4072,"R",3432,"R",640,"R",4072,"R",3948,"R",744,"R",4692,.,.,"R",6864,"R",640,"R",7504,"R",6864,"R",640,"R",7504,"R",6864,"R",640,"R",7504,"R",7894,"R",744,"R",8638,.,.,"R",1800,"R",1800,"R",1800,"R",1800,"R",4770,"R",4770,"R",4770,"R",5350,"R",2600,"R",2600,"R",2600,"R",2080,"R",4770,"R",4770,"R",4770,"R",5350,"R",2600,"R",2600,"R",2600,"R",2080,"R",1300,"R",1300,"R",1300,"R",1300,"A",.,"A",.,"A",.,"A",.,-2,"A",.,"A",.,"A",.,"A",.,-2,"A",.,"A",.,"A",.,"A",.,-2,
diff --git a/tests/static/ic2020.csv b/tests/static/ic2020.csv
new file mode 100644
index 0000000..f0eec2f
--- /dev/null
+++ b/tests/static/ic2020.csv
@@ -0,0 +1,3 @@
+UNITID,PEO1ISTR,PEO2ISTR,PEO3ISTR,PEO4ISTR,PEO5ISTR,PEO6ISTR,CNTLAFFI,PUBPRIME,PUBSECON,RELAFFIL,LEVEL1,LEVEL1A,LEVEL1B,LEVEL2,LEVEL3,LEVEL4,LEVEL5,LEVEL6,LEVEL7,LEVEL8,LEVEL12,LEVEL17,LEVEL18,LEVEL19,CALSYS,FT_UG,FT_FTUG,FTGDNIDP,PT_UG,PT_FTUG,PTGDNIDP,DOCPP,DOCPPSP,OPENADMP,VET1,VET2,VET3,VET4,VET5,VET9,CREDITS1,CREDITS2,CREDITS3,CREDITS4,SLO5,SLO51,SLO52,SLO53,SLO6,SLO7,SLO8,SLO81,SLO82,SLO83,SLO9,YRSCOLL,STUSRV1,STUSRV2,STUSRV3,STUSRV4,STUSRV8,STUSRV9,LIBRES1,LIBRES2,LIBRES3,LIBRES4,LIBRES5,LIBRES6,LIBRES9,TUITPL,TUITPL1,TUITPL2,TUITPL3,TUITPL4,DSTNUGC,DSTNUGP,DSTNUGN,DSTNGC,DSTNGP,DSTNGN,DISTCRS,DISTPGS,DSTNCED1,DSTNCED2,DSTNCED3,DISTNCED,DISAB,XDISABPC,DISABPCT,ALLONCAM,TUITVARY,ROOM,XROOMCAP,ROOMCAP,BOARD,XMEALSWK,MEALSWK,XROOMAMT,ROOMAMT,XBORDAMT,BOARDAMT,XRMBDAMT,RMBRDAMT,XAPPFEEU,APPLFEEU,XAPPFEEG,APPLFEEG,ATHASSOC,ASSOC1,ASSOC2,ASSOC3,ASSOC4,ASSOC5,ASSOC6,SPORT1,CONFNO1,SPORT2,CONFNO2,SPORT3,CONFNO3,SPORT4,CONFNO4 
+100654,0,1,0,0,0,0,1,2,0,-2,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,1,1,1,1,1,-2,-2,2,1,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,-2,1,1,1,1,1,0,1,1,1,1,1,1,0,1,0,0,1,0,1,1,0,1,1,0,1,1,1,1,0,2,1,"A",. ,2,1,1,"R",3220,1,"R",19,"R",3682,"R",3840,"A",.,"R",30,"R",45,1,1,0,0,0,0,0,1,133,1,133,1,133,1,133
+100663,0,1,1,0,0,0,1,2,0,-2,0,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,0,-2,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,0,1,0,1,1,0,1,1,0,1,1,1,1,0,2,2,"R",8 ,2,1,1,"R",2882,2,"A",.,"R",7767,"R",4540,"A",.,"R",40,"R",50,1,1,0,0,0,0,0,1,111,1,111,1,111,1,111
diff --git a/tests/static/om2017.csv b/tests/static/om2017.csv
new file mode 100644
index 0000000..953d3a6
--- /dev/null
+++ b/tests/static/om2017.csv
@@ -0,0 +1,3 @@
+UNITID,OMCHRT,XOMRCHRT,OMRCHRT,XOMEXCLS,OMEXCLS,XOMACHRT,OMACHRT,XOMCERT4,OMCERT4,XOMASSC4,OMASSC4,XOMBACH4,OMBACH4,XOMAWDN4,OMAWDN4,XOMAWDP4,OMAWDP4,XOMCERT6,OMCERT6,XOMASSC6,OMASSC6,XOMBACH6,OMBACH6,XOMAWDN6,OMAWDN6,XOMAWDP6,OMAWDP6,XOMCERT8,OMCERT8,XOMASSC8,OMASSC8,XOMBACH8,OMBACH8,XOMAWDN8,OMAWDN8,XOMENRYI,OMENRYI,XOMENRAI,OMENRAI,XOMENRUN,OMENRUN,XOMNOAWD,OMNOAWD,XOMAWDP8,OMAWDP8,XOMENRTP,OMENRTP,XOMENRYP,OMENRYP,XOMENRAP,OMENRAP,XOMENRUP,OMENRUP 
+100654,10,"R",1092,"R",0,"R",1092,"R",0,"R",0,"R",117,"R",117,"R",11,"R",0,"R",0,"R",333,"R",333,"R",30,"R",0,"R",0,"R",376,"R",376,"R",31,"R",455,"R",230,"R",716,"R",34,"R",45,"R",3,"R",42,"R",21
+100654,11,"R",765,"R",0,"R",765,"R",0,"R",0,"R",69,"R",69,"R",9,"R",0,"R",0,"R",214,"R",214,"R",28,"R",0,"R",0,"R",243,"R",243,"R",22,"R",324,"R",176,"R",522,"R",32,"R",45,"R",3,"R",42,"R",23
diff --git a/tests/static/sfa1617.csv b/tests/static/sfa1617.csv
new file mode 100644
index 0000000..1cb24b2
--- /dev/null
+++ b/tests/static/sfa1617.csv
@@ -0,0 +1,3 @@
+UNITID,XSCUGRAD,SCUGRAD,XSCUGFFN,SCUGFFN,XSCUGFFP,SCUGFFP,XSCFA2,SCFA2,XSCFA1N,SCFA1N,XSCFA1P,SCFA1P,XSCFA11N,SCFA11N,XSCFA11P,SCFA11P,XSCFA12N,SCFA12N,XSCFA12P,SCFA12P,XSCFA13N,SCFA13N,XSCFA13P,SCFA13P,XSCFA14N,SCFA14N,XSCFA14P,SCFA14P,XSCFY2,SCFY2,XSCFY1N,SCFY1N,XSCFY1P,SCFY1P,XSCFY11N,SCFY11N,XSCFY11P,SCFY11P,XSCFY12N,SCFY12N,XSCFY12P,SCFY12P,XSCFY13N,SCFY13N,XSCFY13P,SCFY13P,XSCFY14N,SCFY14N,XSCFY14P,SCFY14P,XUAGRNTN,UAGRNTN,XUAGRNTP,UAGRNTP,XUAGRNTT,UAGRNTT,XUAGRNTA,UAGRNTA,XUPGRNTN,UPGRNTN,XUPGRNTP,UPGRNTP,XUPGRNTT,UPGRNTT,XUPGRNTA,UPGRNTA,XUFLOANN,UFLOANN,XUFLOANP,UFLOANP,XUFLOANT,UFLOANT,XUFLOANA,UFLOANA,XANYAIDN,ANYAIDN,XANYAIDP,ANYAIDP,XAIDFSIN,AIDFSIN,XAIDFSIP,AIDFSIP,XAGRNT_N,AGRNT_N,XAGRNT_P,AGRNT_P,XAGRNT_T,AGRNT_T,XAGRNT_A,AGRNT_A,XFGRNT_N,FGRNT_N,XFGRNT_P,FGRNT_P,XFGRNT_T,FGRNT_T,XFGRNT_A,FGRNT_A,XPGRNT_N,PGRNT_N,XPGRNT_P,PGRNT_P,XPGRNT_T,PGRNT_T,XPGRNT_A,PGRNT_A,XOFGRT_N,OFGRT_N,XOFGRT_P,OFGRT_P,XOFGRT_T,OFGRT_T,XOFGRT_A,OFGRT_A,XSGRNT_N,SGRNT_N,XSGRNT_P,SGRNT_P,XSGRNT_T,SGRNT_T,XSGRNT_A,SGRNT_A,XIGRNT_N,IGRNT_N,XIGRNT_P,IGRNT_P,XIGRNT_T,IGRNT_T,XIGRNT_A,IGRNT_A,XLOAN_N,LOAN_N,XLOAN_P,LOAN_P,XLOAN_T,LOAN_T,XLOAN_A,LOAN_A,XFLOAN_N,FLOAN_N,XFLOAN_P,FLOAN_P,XFLOAN_T,FLOAN_T,XFLOAN_A,FLOAN_A,XOLOAN_N,OLOAN_N,XOLOAN_P,OLOAN_P,XOLOAN_T,OLOAN_T,XOLOAN_A,OLOAN_A,XGISTN2,GISTN2,XGISTON2,GISTON2,XGISTWF2,GISTWF2,XGISTOF2,GISTOF2,XGISTUN2,GISTUN2,XGISTT2,GISTT2,XGISTA2,GISTA2,XGISTN1,GISTN1,XGISTON1,GISTON1,XGISTWF1,GISTWF1,XGISTOF1,GISTOF1,XGISTUN1,GISTUN1,XGISTT1,GISTT1,XGISTA1,GISTA1,XGISTN0,GISTN0,XGISTON0,GISTON0,XGISTWF0,GISTWF0,XGISTOF0,GISTOF0,XGISTUN0,GISTUN0,XGISTT0,GISTT0,XGISTA0,GISTA0,XGIS4N2,GIS4N2,XGIS4ON2,GIS4ON2,XGIS4OF2,GIS4OF2,XGIS4WF2,GIS4WF2,XGIS4UN2,GIS4UN2,XGIS4G2,GIS4G2,XGIS4T2,GIS4T2,XGIS4A2,GIS4A2,XGIS4N12,GIS4N12,XGIS4G12,GIS4G12,XGIS4T12,GIS4T12,XGIS4A12,GIS4A12,XGIS4N22,GIS4N22,XGIS4G22,GIS4G22,XGIS4T22,GIS4T22,XGIS4A22,GIS4A22,XGIS4N32,GIS4N32,XGIS4G32,GIS4G32,XGIS4T32,GIS4T32,XGIS4A32,GIS4A32,XGIS4N42,GIS4N42,XGIS4G42,GIS4G42,XGIS4T42,GIS4T42,XGIS4A42,GIS4A42,XGIS4N52,GIS4N52,XGIS4G52,GIS4G52,XGIS4T52,GIS4T52,XGIS4A52,GIS4A52,XGIS4N1,GIS4N1,XGIS4ON1,GIS4ON1,XGIS4OF1,GIS4OF1,XGIS4WF1,GIS4WF1,XGIS4UN1,GIS4UN1,XGIS4G1,GIS4G1,XGIS4T1,GIS4T1,XGIS4A1,GIS4A1,XGIS4N11,GIS4N11,XGIS4G11,GIS4G11,XGIS4T11,GIS4T11,XGIS4A11,GIS4A11,XGIS4N21,GIS4N21,XGIS4G21,GIS4G21,XGIS4T21,GIS4T21,XGIS4A21,GIS4A21,XGIS4N31,GIS4N31,XGIS4G31,GIS4G31,XGIS4T31,GIS4T31,XGIS4A31,GIS4A31,XGIS4N41,GIS4N41,XGIS4G41,GIS4G41,XGIS4T41,GIS4T41,XGIS4A41,GIS4A41,XGIS4N51,GIS4N51,XGIS4G51,GIS4G51,XGIS4T51,GIS4T51,XGIS4A51,GIS4A51,XGIS4N0,GIS4N0,XGIS4ON0,GIS4ON0,XGIS4OF0,GIS4OF0,XGIS4WF0,GIS4WF0,XGIS4UN0,GIS4UN0,XGIS4G0,GIS4G0,XGIS4T0,GIS4T0,XGIS4A0,GIS4A0,XGIS4N10,GIS4N10,XGIS4G10,GIS4G10,XGIS4T10,GIS4T10,XGIS4A10,GIS4A10,XGIS4N20,GIS4N20,XGIS4G20,GIS4G20,XGIS4T20,GIS4T20,XGIS4A20,GIS4A20,XGIS4N30,GIS4N30,XGIS4G30,GIS4G30,XGIS4T30,GIS4T30,XGIS4A30,GIS4A30,XGIS4N40,GIS4N40,XGIS4G40,GIS4G40,XGIS4T40,GIS4T40,XGIS4A40,GIS4A40,XGIS4N50,GIS4N50,XGIS4G50,GIS4G50,XGIS4T50,GIS4T50,XGIS4A50,GIS4A50,XNPIST2,NPIST2,XNPIST1,NPIST1,XNPIST0,NPIST0,XNPIS412,NPIS412,XNPIS422,NPIS422,XNPIS432,NPIS432,XNPIS442,NPIS442,XNPIS452,NPIS452,XNPIS411,NPIS411,XNPIS421,NPIS421,XNPIS431,NPIS431,XNPIS441,NPIS441,XNPIS451,NPIS451,XNPIS410,NPIS410,XNPIS420,NPIS420,XNPIS430,NPIS430,XNPIS440,NPIS440,XNPIS450,NPIS450,XGRNTN2,GRNTN2,XGRNTON2,GRNTON2,XGRNTWF2,GRNTWF2,XGRNTOF2,GRNTOF2,XGRNTUN2,GRNTUN2,XGRNTT2,GRNTT2,XGRNTA2,GRNTA2,XGRNTN1,GRNTN1,XGRNTON1,GRNTON1,XGRNTWF1,GRNTWF1,XGRNTOF1,GRNTOF1,XGRNTUN1,GRNTUN1,XGRNTT1,GRNTT1,XGRNTA1,GRNTA1,XGRNTN0,GRNTN0,XGRNTON0,GRNTON0,XGRNTWF0,GRNTWF0,XGRNTOF0,GRNTOF0,XGRNTUN0,GRNTUN0,XGRNTT0,GRNTT0,XGRNTA0,GRNTA0,XGRN4N2,GRN4N2,XGRN4ON2,GRN4ON2,XGRN4OF2,GRN4OF2,XGRN4WF2,GRN4WF2,XGRN4UN2,GRN4UN2,XGRN4G2,GRN4G2,XGRN4T2,GRN4T2,XGRN4A2,GRN4A2,XGRN4N12,GRN4N12,XGRN4G12,GRN4G12,XGRN4T12,GRN4T12,XGRN4A12,GRN4A12,XGRN4N22,GRN4N22,XGRN4G22,GRN4G22,XGRN4T22,GRN4T22,XGRN4A22,GRN4A22,XGRN4N32,GRN4N32,XGRN4G32,GRN4G32,XGRN4T32,GRN4T32,XGRN4A32,GRN4A32,XGRN4N42,GRN4N42,XGRN4G42,GRN4G42,XGRN4T42,GRN4T42,XGRN4A42,GRN4A42,XGRN4N52,GRN4N52,XGRN4G52,GRN4G52,XGRN4T52,GRN4T52,XGRN4A52,GRN4A52,XGRN4N1,GRN4N1,XGRN4ON1,GRN4ON1,XGRN4OF1,GRN4OF1,XGRN4WF1,GRN4WF1,XGRN4UN1,GRN4UN1,XGRN4G1,GRN4G1,XGRN4T1,GRN4T1,XGRN4A1,GRN4A1,XGRN4N11,GRN4N11,XGRN4G11,GRN4G11,XGRN4T11,GRN4T11,XGRN4A11,GRN4A11,XGRN4N21,GRN4N21,XGRN4G21,GRN4G21,XGRN4T21,GRN4T21,XGRN4A21,GRN4A21,XGRN4N31,GRN4N31,XGRN4G31,GRN4G31,XGRN4T31,GRN4T31,XGRN4A31,GRN4A31,XGRN4N41,GRN4N41,XGRN4G41,GRN4G41,XGRN4T41,GRN4T41,XGRN4A41,GRN4A41,XGRN4N51,GRN4N51,XGRN4G51,GRN4G51,XGRN4T51,GRN4T51,XGRN4A51,GRN4A51,XGRN4N0,GRN4N0,XGRN4ON0,GRN4ON0,XGRN4OF0,GRN4OF0,XGRN4WF0,GRN4WF0,XGRN4UN0,GRN4UN0,XGRN4G0,GRN4G0,XGRN4T0,GRN4T0,XGRN4A0,GRN4A0,XGRN4N10,GRN4N10,XGRN4G10,GRN4G10,XGRN4T10,GRN4T10,XGRN4A10,GRN4A10,XGRN4N20,GRN4N20,XGRN4G20,GRN4G20,XGRN4T20,GRN4T20,XGRN4A20,GRN4A20,XGRN4N30,GRN4N30,XGRN4G30,GRN4G30,XGRN4T30,GRN4T30,XGRN4A30,GRN4A30,XGRN4N40,GRN4N40,XGRN4G40,GRN4G40,XGRN4T40,GRN4T40,XGRN4A40,GRN4A40,XGRN4N50,GRN4N50,XGRN4G50,GRN4G50,XGRN4T50,GRN4T50,XGRN4A50,GRN4A50,XNPGRN2,NPGRN2,XNPGRN1,NPGRN1,XNPGRN0,NPGRN0,XNPT412,NPT412,XNPT422,NPT422,XNPT432,NPT432,XNPT442,NPT442,XNPT452,NPT452,XNPT411,NPT411,XNPT421,NPT421,XNPT431,NPT431,XNPT441,NPT441,XNPT451,NPT451,XNPT410,NPT410,XNPT420,NPT420,XNPT430,NPT430,XNPT440,NPT440,XNPT450,NPT450  
+100654,"R",4851,"R",1410,"R",29,"R",4851,"R",1410,"R",29,"R",0,"Z",0,"R",858,"R",61,"R",552,"R",39,"R",0,"Z",0,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"R",4225,"R",87,"R",41598091,"R",9846,"R",3444,"R",71,"R",15953983,"R",4632,"R",3734,"R",77,"R",26139680,"R",7000,"R",1296,"R",92,"R",1272,"R",90,"R",1212,"R",86,"R",9765592,"R",8057,"R",1002,"R",71,"R",4815142,"R",4806,"R",1002,"R",71,"R",4683617,"R",4674,"R",55,"R",4,"R",131525,"R",2391,"R",87,"R",6,"R",751194,"R",8634,"R",775,"R",55,"R",4199256,"R",5418,"R",1051,"R",75,"R",6622483,"R",6301,"R",1046,"R",74,"R",6412830,"R",6131,"R",24,"R",2,"R",209653,"R",8736,"R",858,"R",718,"R",0,"R",140,"R",0,"R",6069396,"R",7074,"R",968,"R",874,"R",31,"R",63,"R",0,"R",6861607,"R",7088,"R",777,"R",703,"R",24,"R",40,"R",10,"R",5873277,"R",7559,"R",736,"R",654,"R",82,"R",0,"R",0,"R",718,"R",5668723,"R",7702,"R",428,"R",428,"R",3495276,"R",8167,"R",153,"R",153,"R",1291194,"R",8439,"R",88,"R",81,"R",540296,"R",6140,"R",43,"R",37,"R",247637,"R",5759,"R",24,"R",19,"R",94320,"R",3930,"R",924,"R",839,"R",59,"R",26,"R",0,"R",924,"R",6560575,"R",7100,"R",623,"R",623,"R",4749717,"R",7624,"R",172,"R",172,"R",1234224,"R",7176,"R",75,"R",75,"R",399887,"R",5332,"R",41,"R",41,"R",127325,"R",3105,"R",13,"R",13,"R",49422,"R",3802,"R",743,"R",682,"R",41,"R",20,"R",0,"R",723,"R",5479145,"R",7374,"R",485,"R",483,"R",3751145,"R",7734,"R",129,"R",128,"R",1077277,"R",8351,"R",76,"R",66,"R",376360,"R",4952,"R",38,"R",32,"R",181917,"R",4787,"R",15,"R",14,"R",92446,"R",6163,"R",15812,"R",15547,"R",13203,"R",14719,"R",14447,"R",16746,"R",17127,"R",18956,"R",15043,"R",15491,"R",17335,"R",19562,"R",18865,"R",13075,"R",12458,"R",15857,"R",16022,"R",14646,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",
+100663,"R",12369,"R",1948,"R",16,"R",12369,"R",1948,"R",16,"R",0,"Z",0,"R",1654,"R",85,"R",294,"R",15,"R",0,"Z",0,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"R",7491,"R",61,"R",59122724,"R",7893,"R",4369,"R",35,"R",19483264,"R",4459,"R",6441,"R",52,"R",46945593,"R",7289,"R",1837,"R",94,"R",1807,"R",93,"R",1689,"R",87,"R",15629595,"R",9254,"R",781,"R",40,"R",3992347,"R",5112,"R",781,"R",40,"R",3709480,"R",4750,"R",199,"R",10,"R",282867,"R",1421,"R",7,"R",0,"R",37357,"R",5337,"R",1449,"R",74,"R",11599891,"R",8005,"R",1086,"R",56,"R",7784870,"R",7168,"R",1069,"R",55,"R",6538553,"R",6117,"R",110,"R",6,"R",1246317,"R",11330,"R",1416,"R",1156,"R",176,"R",66,"R",18,"R",10366090,"R",7321,"R",1128,"R",859,"R",175,"R",48,"R",46,"R",7694524,"R",6821,"R",1190,"R",907,"R",184,"R",63,"R",36,"R",8223289,"R",6910,"R",1120,"R",880,"R",79,"R",161,"R",0,"R",1008,"R",7384965,"R",6594,"R",374,"R",372,"R",3309399,"R",8849,"R",216,"R",214,"R",1603077,"R",7422,"R",173,"R",149,"R",906356,"R",5239,"R",165,"R",129,"R",709304,"R",4299,"R",192,"R",144,"R",856829,"R",4463,"R",820,"R",614,"R",56,"R",150,"R",0,"R",741,"R",5091346,"R",6209,"R",280,"R",277,"R",2473828,"R",8835,"R",140,"R",139,"R",1021905,"R",7299,"R",137,"R",118,"R",638754,"R",4662,"R",117,"R",93,"R",465600,"R",3979,"R",146,"R",114,"R",491259,"R",3365,"R",955,"R",701,"R",62,"R",192,"R",0,"R",835,"R",5929255,"R",6209,"R",359,"R",358,"R",3093740,"R",8618,"R",146,"R",142,"R",1092962,"R",7486,"R",134,"R",114,"R",620538,"R",4631,"R",161,"R",112,"R",540806,"R",3359,"R",155,"R",109,"R",581209,"R",3750,"R",17016,"R",16092,"R",15772,"R",15280,"R",16707,"R",18890,"R",19830,"R",19666,"R",13849,"R",15385,"R",18022,"R",18705,"R",19319,"R",13614,"R",14746,"R",17601,"R",18873,"R",18482,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",,"A",
diff --git a/tests/test_ipeds.py b/tests/test_ipeds.py
new file mode 100644
index 0000000..2e7f64f
--- /dev/null
+++ b/tests/test_ipeds.py
@@ -0,0 +1,212 @@
+from pathlib import Path
+from unittest import mock
+
+import pandas as pd
+import pytest
+
+from pypeds import C_A, EFC, EFD, FF1, FF2, HD, IC, ICAY, OM, SFA
+
+loader_classes = (HD, IC, SFA, EFC, ICAY, OM, EFD, FF1, FF2, C_A)
+
+
+def get_test_csv_path(loader_class) -> Path:
+    csv_base_path = Path("./tests/static")
+    csv_file_names = {
+        "C_A": "c2020_a.csv",
+        "EFC": "ef2017c.csv",
+        "EFD": "ef2017d.csv",
+        "FF1": "f1920_f1a.csv",
+        "FF2": "f1920_f2.csv",
+        "HD": "hd2020.csv",
+        "IC": "ic2020.csv",
+        "ICAY": "ic2009_ay.csv",
+        "OM": "om2017.csv",
+        "SFA": "sfa1617.csv",
+    }
+    return csv_base_path / csv_file_names[loader_class.__name__]
+
+
+def get_survey_id(loader_class, year: int) -> str:
+    survey_ids = {
+        C_A: "C" + str(year) + "_A",
+        EFC: "EF" + str(year) + "C",
+        EFD: "EF" + str(year) + "D",
+        FF1: "F" + str(year - 1)[2:] + str(year)[2:] + "_F1A",
+        FF2: "F" + str(year - 1)[2:] + str(year)[2:] + "_F2",
+        HD: "HD" + str(year),
+        IC: "IC" + str(year),
+        ICAY: "IC" + str(year) + "_AY",
+        OM: "OM" + str(year),
+        SFA: "SFA" + str(year - 1)[2:] + str(year)[2:],
+    }
+    return survey_ids[loader_class]
+
+
+def get_url(survey_id: str):
+    return f"https://nces.ed.gov/ipeds/datacenter/data/{survey_id}.zip"
+
+
+@pytest.fixture
+def ipeds_df():
+    return pd.DataFrame({"UNITID": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})
+
+
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_classes_initialize_correct_instance_vars(loader_class):
+    """Calling a loader class (e.g., `HD()`) creates two instance variables:
+    a dataframe called `df` and an array of integers called `years`.
+    """
+    loader_inst = loader_class()
+    inst_vars = [
+        attr
+        for attr in dir(loader_inst)
+        if not callable(getattr(loader_inst, attr))
+        and not attr.startswith("__")
+    ]
+    assert set(inst_vars) == set(["df", "years"])
+    assert isinstance(loader_inst.df, pd.DataFrame)
+    assert isinstance(loader_inst.years, list)
+
+
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_classes_initialize_with_single_default_year_in_list(loader_class):
+    """Calling a loader class without passing in any arguments sets the `years`
+    instance variable to a list with a single integer year in it.
+    """
+    loader_inst = loader_class()
+    assert len(loader_inst.years) == 1
+    assert isinstance(loader_inst.years[0], int)
+
+
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_passing_year_list_to_loader_populates_years_var(loader_class):
+    """Passing one or more years in a list to the `years` parameter sets
+    the instance's `years` variable to a list of those years.
+    """
+    loader_inst_one_year = loader_class(years=[2015])
+    loader_inst_multi_year = loader_class(years=[2014, 2015, 2016])
+    assert loader_inst_one_year.years == [2015]
+    assert loader_inst_multi_year.years == [2014, 2015, 2016]
+
+
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_initial_dataframe_is_empty(loader_class):
+    """The loader classes' `self.df` instance variable is initially empty."""
+    loader_inst = loader_class()
+    assert len(loader_inst.df) == 0
+
+
+@mock.patch("pypeds.ipeds.os.remove")
+@mock.patch("pypeds.ipeds.read_survey")
+@mock.patch("pypeds.ipeds.zip_parser")
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_extract_requests_data_from_correct_url(
+    mock_zip_parser, mock_read_survey, mock_remove, loader_class, ipeds_df
+):
+    """Calling `extract` on a loader class sends a GET request to the
+    correct URL.
+    """
+    mock_read_survey.return_value = ipeds_df
+    loader_inst = loader_class(years=[2015])
+    loader_inst.extract()
+
+    survey_id = get_survey_id(loader_class, 2015)
+    url = get_url(survey_id)
+
+    if loader_class != IC:
+        mock_zip_parser.assert_called_with(url=url, survey=survey_id)
+
+    # IC starting in 2014 combines IC and ADM
+    else:
+        assert mock_zip_parser.call_args_list[0] == mock.call(
+            url="https://nces.ed.gov/ipeds/datacenter/data/IC2015.zip",
+            survey="IC2015",
+        )
+        assert mock_zip_parser.call_args_list[1] == mock.call(
+            url="https://nces.ed.gov/ipeds/datacenter/data/ADM2015.zip",
+            survey="ADM2015",
+        )
+
+
+@mock.patch("pypeds.ipeds.os.remove")
+@mock.patch("pypeds.ipeds.zip_parser")
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_extract_fills_df_with_data(
+    mock_zip_parser, mock_remove, loader_class
+):
+    """Calling `extract` on a loader class fills the empty `df` instance
+    variable with data.
+    """
+    mock_zip_parser.return_value = get_test_csv_path(loader_class)
+    loader_inst = loader_class()
+    loader_inst.extract()
+    assert len(loader_inst.df) == 2
+
+
+@mock.patch("pypeds.ipeds.read_survey")
+@mock.patch("pypeds.ipeds.zip_parser")
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_extract_calls_supporting_funcs_once_for_each_year(
+    mock_zip_parser, mock_reader, loader_class, ipeds_df
+):
+    """Calling `extract` on a loader class calls the `zip_parser` and
+    `read_survey` functions once for each year included in the load class's
+    `years` list argument.
+
+    The exception to this is the `IC` loader class, which calls each function
+    twice--once for the IC survey and once for the ADM survey, which it then
+    merges together.
+    """
+    mock_reader.return_value = ipeds_df
+    years = [2015, 2016, 2017]
+    loader_inst = loader_class(years=years)
+    loader_inst.extract()
+
+    if loader_class.__name__ != "IC":
+        assert mock_zip_parser.call_count == len(years)
+        assert mock_reader.call_count == len(years)
+
+    # `IC` loads both IC and ADM and merges them together
+    else:
+        assert mock_zip_parser.call_count == len(years) * 2
+        assert mock_reader.call_count == len(years) * 2
+
+
+@mock.patch("pypeds.ipeds.os.remove")
+@mock.patch("pypeds.ipeds.read_survey")
+@mock.patch("pypeds.ipeds.zip_parser")
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_extract_adds_year_columns_to_df(
+    mock_zip_parser, mock_read_survey, mock_remove, loader_class, ipeds_df
+):
+    """Calling `extract` adds `survey_year` and `fall_year` columns to the `df`
+    instance variable.
+    """
+    mock_read_survey.return_value = ipeds_df
+    loader_inst = loader_class()
+    loader_inst.extract()
+    assert "survey_year" in loader_inst.df.columns
+    assert "fall_year" in loader_inst.df.columns
+
+
+@mock.patch("pypeds.ipeds.os.remove")
+@mock.patch("pypeds.ipeds.read_survey")
+@mock.patch("pypeds.ipeds.zip_parser")
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_extract_converts_df_columns_to_lowercase(
+    mock_zip_parser, mock_read_survey, mock_remove, loader_class, ipeds_df
+):
+    """Calling `extract` makes all `df` instance variable columns lowercase."""
+    mock_read_survey.return_value = ipeds_df
+    loader_inst = loader_class()
+    loader_inst.extract()
+    assert all(col.islower() for col in loader_inst.df.columns)
+
+
+@pytest.mark.parametrize("loader_class", loader_classes)
+def test_load_returns_df_instance_var(loader_class):
+    """Calling the `load()` method on a loader instance returns the instance's
+    `df` variable.
+    """
+    loader_inst = loader_class()
+    assert loader_inst.load() is loader_inst.df